home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 23 / CU Amiga - Super CD-ROM 23 (June 1998).iso / CreatingGames / GameCreators / TADS / ditch.t < prev    next >
Encoding:
Text File  |  1996-11-22  |  108.3 KB  |  3,896 lines

  1. /*  Copyright (c) 1990 by Michael J. Roberts.  All Rights Reserved. */
  2. /*
  3.     Ditch Day Drifter
  4.     Interactive Fiction by Michael J. Roberts.
  5.     
  6.     Developed with TADS: The Text Adventure Development System.
  7.     
  8.     This game is a sample TADS source file.  It demonstrates many of the
  9.     features of TADS.  The TADS language is fully documented in the TADS
  10.     Author's Manual, which is freely available in electronic format;
  11.     you can probably get a copy of the Author's Manual from the same
  12.     place you obtained this file.
  13.     
  14.     Please read LICENSE.DOC for information about using and copying this
  15.     file, and about registering your copy of TADS.
  16. */
  17.  
  18. /*
  19.  *   First, insert the file containing the standard adventure definitions.
  20.  */
  21. #include <adv.t>
  22.  
  23. /*
  24.  *   Pre-declare some functions, so the compiler knows they are functions.
  25.  *   (This is only really necessary when a function will be referenced
  26.  *   as a daemon or fuse before it is defined; however, it doesn't hurt
  27.  *   anything to pre-declare all of them.)
  28.  */
  29. die: function;
  30. scoreRank: function;
  31. init: function;
  32. terminate: function;
  33. pardon: function;
  34. sleepDaemon: function;
  35. eatDaemon: function;
  36. darkTravel: function;
  37. ;
  38.  
  39. /* provide a preparse function, but don't bother doing anything */
  40. preparse: function(cmd)
  41. {
  42.     return(true);
  43. }
  44.  
  45. /* likewise, provide a parseError function that doesn't do anything */
  46. parseError: function(num, str)
  47. {
  48.     return(nil);
  49. }
  50.  
  51. /*
  52.  *   Provide the default implementation of commandPrompt.  This has the
  53.  *   same effect as leaving the function out altogether, but it avoids a
  54.  *   compiler warning to have it defined. 
  55.  */
  56. commandPrompt: function(typ)
  57. {
  58.     "\b>";
  59. }
  60.  
  61.  
  62. /*
  63.  *   The die() function is called when the player dies.  It tells the
  64.  *   player how well he has done (with his score), and asks if he'd
  65.  *   like to start over (the alternative being quitting the game).
  66.  */
  67. die: function
  68. {
  69.     "\b*** You have died ***\b";
  70.     scoreRank();
  71.  
  72.     /*
  73.      *   Check if the player (Me) purchased insurance.  If so, issue
  74.      *   an appropriate message.
  75.      */
  76.     if ( Me.isinsured )
  77.         "\bI'm sure that Lloyd is even now paying out a big lump sum for
  78.     your early demise. However, that is of little use to you now. ";
  79.  
  80.     /*
  81.      *   Tell the user the options available, and then ask for some
  82.      *   input.  Keep asking until we get something we recognize.
  83.      */
  84.     "\bYou may restore a saved game, start over, undo the
  85.     last move, or quit. ";
  86.     while ( 1 )
  87.     {
  88.         local resp;
  89.  
  90.     "\nPlease enter RESTORE, RESTART, UNDO, or QUIT: >";
  91.         resp := upper(input());     /* get input, convert to uppercase */
  92.         if ( resp = 'RESTORE' )
  93.     {
  94.         resp := askfile( 'File to restore' );       /* find filename */
  95.         if ( resp = nil ) "Restore failed. ";
  96.         else if ( restore( resp )) "Restore failed. ";
  97.         else
  98.         {
  99.             /*
  100.          *   We've successfully restored a game.  Reset the status
  101.          *   line's score/turn counter, and resume play.
  102.          */
  103.             setscore( global.score, global.turnsofar );
  104.         abort;
  105.         }
  106.     }
  107.         else if ( resp = 'RESTART' )
  108.     {
  109.         /*
  110.          *   We're going to start over.  Reset the status line's
  111.          *   score/turn counter and start from the beginning.
  112.          */
  113.         setscore( 0, 0 );
  114.             restart();
  115.     }
  116.     else if ( resp = 'UNDO' )
  117.     {
  118.         if (undo())
  119.         {
  120.         "(Undoing one command)\b";
  121.         Me.location.lookAround(true);
  122.         setscore(global.score, global.turnsofar);
  123.         abort;
  124.         }
  125.         else
  126.         "Sorry, no undo information is available.";
  127.     }
  128.     else if ( resp = 'QUIT' )
  129.         {
  130.         /*
  131.          *   We're quitting the game.  Do any final activity necessary,
  132.          *   and exit.
  133.          */
  134.         terminate();
  135.             quit();
  136.         abort;
  137.         }
  138.     }
  139. }
  140.  
  141. /*
  142.  *   The scoreRank() function displays how well the player is doing.
  143.  *   In addition to displaying the numerical score and number of turns
  144.  *   played so far, we'll classify the score with a rank such as "sophomore."
  145.  *
  146.  *   Note that "global.maxscore" defines the maximum number of points
  147.  *   possible in the game.
  148.  */
  149. scoreRank: function
  150. {
  151.     local s;
  152.     
  153.     s := global.score;
  154.     
  155.     "In a total of "; say( global.turnsofar );
  156.     " turns, you have achieved a score of ";
  157.     say( s ); " points out of a possible "; say( global.maxscore );
  158.     ", which gives you a rank of ";
  159.     
  160.     if ( s < 10 ) "high-school hopeful";
  161.     else if ( s < 25 ) "freshman";
  162.     else if ( s < 40 ) "sophomore";
  163.     else if ( s < 60 ) "junior";
  164.     else if ( s < global.maxscore ) "senior";
  165.     else "graduate";
  166.     
  167.     ". ";
  168. }
  169.  
  170. /*
  171.  *   The init() function is run at the very beginning of the game.
  172.  *   We display some introductory text, then move the player (Me) to the
  173.  *   initial location and set up some background activity.
  174.  */
  175. init: function
  176. {
  177.     setscore(0, 0);                   // set up the initial status line display
  178.     
  179.     "\tYou wake up to the sound of voices in the hall. You are confused for
  180.     a moment; it's only 8 AM, far too early for anyone to be getting up.
  181.     Then, it dawns on you: it's ditch day here at the fictitious California
  182.     Institute of Technology in the mythical city of Pasadena, California.
  183.     Ditch Day, that strange tradition wherein seniors bar their doors with
  184.     various devices and underclassmen attempt to defeat these devices (for
  185.     no other apparent reason than that the devices are there), has arrived.\b";
  186.     
  187.     version.sdesc;                // display the game's name and version number
  188.     "\b";
  189.     
  190.     setdaemon( turncount, nil );               // start the turn counter daemon
  191.     setdaemon( sleepDaemon, nil );                    // start the sleep daemon
  192.     setdaemon( eatDaemon, nil );                     // start the hunger daemon
  193.     Me.location := startroom;                // move player to initial location
  194.     startroom.lookAround( true );                    // show player where he is
  195.     startroom.isseen := true;
  196. }
  197.  
  198. /*
  199.  *   preinit() is called after compiling the game, before it is written
  200.  *   to the binary game file.  It performs all the initialization that can
  201.  *   be done statically before storing the game in the file, which speeds
  202.  *   loading the game, since all this work has been done ahead of time.
  203.  *
  204.  *   This routine puts all lamp objects (those objects with islamp = true) into
  205.  *   the list global.lamplist.  This list is consulted when determining whether
  206.  *   a dark room contains any light sources.
  207.  */
  208. preinit: function
  209. {
  210.     local o;
  211.     
  212.     global.lamplist := [];
  213.     o := firstobj(lightsource);
  214.     while( o <> nil )
  215.     {
  216.         if ( o.islamp ) global.lamplist := global.lamplist + o;
  217.         o := nextobj(o, lightsource);
  218.     }
  219.     initSearch();
  220. }
  221.  
  222. /*
  223.  *   The terminate() function is called just before the game ends.  We
  224.  *   just display a good-bye message.
  225.  */
  226. terminate: function
  227. {
  228.     "\bThanks for participating in Ditch Day!\n";
  229. }
  230.  
  231. /*
  232.  *   The pardon() function is called any time the player enters a blank
  233.  *   line.
  234.  */
  235. pardon: function
  236. {
  237.     "I beg your pardon? ";
  238. }
  239.  
  240. /*
  241.  *   This function is a daemon, started by init(), that monitors how long
  242.  *   it has been since the player slept.  It provides warnings for a while
  243.  *   before the player gets completely exhausted, and causes the player
  244.  *   to pass out and sleep when it has been too long.  The only penalty
  245.  *   exacted if the player passes out is that he drops all his possessions.
  246.  *   Some games might also wish to consider the effects of several hours
  247.  *   having passed; for example, the time-without-food count might be
  248.  *   increased accordingly.
  249.  */
  250. sleepDaemon: function( parm )
  251. {
  252.     local a, s;
  253.  
  254.     global.awakeTime := global.awakeTime + 1;
  255.     a := global.awakeTime;
  256.     s := global.sleepTime;
  257.  
  258.     if ( a = s or a = s+10 or a = s+20 )
  259.         "\bYou're feeling a bit drowsy; you should find a
  260.         comfortable place to sleep. ";
  261.     else if ( a = s+25 or a = s+30 )
  262.         "\bYou really should find someplace to sleep soon, or
  263.         you'll probably pass out from exhaustion. ";
  264.     else if ( a >= s+35 )
  265.     {
  266.       global.awakeTime := 0;
  267.       if ( Me.location.isbed or Me.location.ischair )
  268.       {
  269.         "\bYou find yourself unable to stay awake any longer.
  270.         Fortunately, you are ";
  271.         if ( Me.location.isbed ) "on "; else "in ";
  272.         Me.location.adesc; ", so you gently slip off into
  273.         unconsciousness.
  274.         \b* * * * *
  275.         \bYou awake some time later, feeling refreshed. ";
  276.       }
  277.       else
  278.       {
  279.         local itemRem, thisItem;
  280.         "\bYou find yourself unable to stay awake any longer.
  281.         You pass out, falling to the ground.
  282.         \b* * * * *
  283.         \bYou awaken, feeling somewhat the worse for wear.
  284.         You get up and dust yourself off. ";
  285.         itemRem := Me.contents;
  286.         while (car( itemRem ))
  287.         {
  288.             thisItem := car( itemRem );
  289.             if ( not thisItem.isworn ) thisItem.moveInto( Me.location );
  290.         itemRem := cdr( itemRem );
  291.         }
  292.       }
  293.     }
  294. }
  295.  
  296. /*
  297.  *   This function is a daemon, set running by init(), which monitors how
  298.  *   long it has been since the player has had anything to eat.  It will
  299.  *   provide warnings for some time prior to the player's expiring from
  300.  *   hunger, and will kill the player if he should go too long without
  301.  *   heeding these warnings.
  302.  */
  303. eatDaemon: function( parm )
  304. {
  305.     local e, l;
  306.  
  307.     global.lastMealTime := global.lastMealTime + 1;
  308.     e := global.eatTime;
  309.     l := global.lastMealTime;
  310.  
  311.     if ( l = e or l = e+5 or l = e+10 )
  312.         "\bYou're feeling a bit peckish. Perhaps it would be a good
  313.         time to find something to eat. ";
  314.     else if ( l = e+15 or l = e+20 or l = e+25 )
  315.         "\bYou're feeling really hungry. You should find some food
  316.         soon or you'll pass out from lack of nutrition. ";
  317.     else if ( l=e+30 or l = e+35 )
  318.         "\bYou really can't go much longer without food. ";
  319.     else if ( l >= e+40 )
  320.     {
  321.         "\bYou simply can't go on any longer without food. You perish from
  322.         lack of nutrition. ";
  323.         die();
  324.     }
  325. }
  326.  
  327. /*
  328.  *   The numObj object is used to convey a number to the game whenever
  329.  *   the player uses a number in his command.  For example, "turn dial
  330.  *   to 621" results in an indirect object of numObj, with its "value"
  331.  *   property set to 621.  Just pick up the default definition from adv.t.
  332.  */
  333. numObj: basicNumObj
  334. ;
  335.  
  336. /*
  337.  *   strObj works like numObj, but for strings.  So, a player command of
  338.  *     type "hello" on the keyboard
  339.  *   will result in a direct object of strObj, with its "value" property
  340.  *   set to the string 'hello'.
  341.  *
  342.  *   Note that, because a string direct object is used in the save, restore,
  343.  *   and script commands, this object must handle those commands.  We'll just
  344.  *   pick up the default definition from adv.t.
  345.  */
  346. strObj: basicStrObj
  347. ;
  348.  
  349. /*
  350.  *   The "global" object is the dumping ground for any data items that
  351.  *   don't fit very well into any other objects.
  352.  */
  353. global: object
  354.     turnsofar = 0                            // no turns have transpired so far
  355.     score = 0                            // no points have been accumulated yet
  356.     maxscore = 80                                     // maximum possible score
  357.     verbose = nil                             // we are currently in TERSE mode
  358.     awakeTime = 0               // time that has elapsed since the player slept
  359.     sleepTime = 600     // interval between sleeping times (longest time awake)
  360.     lastMealTime = 0              // time that has elapsed since the player ate
  361.     eatTime = 250         // interval between meals (longest time without food)
  362.     lamplist = []              // list of all known light providers in the game
  363. ;
  364.  
  365. /*
  366.  *   The "version" object defines, via its "sdesc" property, the name and
  367.  *   version number of the game.
  368.  */
  369. version: object
  370.     sdesc = "Ditch Day Drifter
  371.      \nInteractive Fiction by Michael J.\ Roberts
  372.      \bRelease 1.0
  373.      \nCopyright (c) 1990 by Michael J.\ Roberts. All Rights Reserved.
  374.      \nDeveloped with TADS: The Text Adventure Development System. "
  375. ;
  376.  
  377. /*
  378.  *   "Me" is the player's actor.  Pick up the default definition, basicMe,
  379.  *   from "adv.t".
  380.  */
  381. Me: basicMe
  382. ;
  383.  
  384. /*
  385.  *   darkTravel() is called whenever the player attempts to move from a dark
  386.  *   location into another dark location.  We don't do much of anything;
  387.  *   some games might impose a probability of walking into the slavering
  388.  *   jaws of a grue, whatever that might be.
  389.  */
  390. darkTravel: function
  391. {
  392.     "You stumble around in the dark, and don't get anywhere. ";
  393. }
  394.  
  395. /*
  396.  *   The player will start in the room called "startroom", by virtue
  397.  *   of being placed there by the "init" function.
  398.  *
  399.  *   All rooms have an sdesc (short description), which is displayed on
  400.  *   the status line and on entry to the room (even if the room has been
  401.  *   seen before).  In addition, the ldesc (long description) is printed
  402.  *   when the player enters the room for the first time or types "look."
  403.  *   Directions (north, south, east, west, ne, nw, se, sw, in, out)
  404.  *   specify where the exits go.  If a direction is not specified, no
  405.  *   exit is in that direction.
  406.  */
  407. startroom: room
  408.     sdesc = "Room 3"                                // short description
  409.     ldesc = "This is your room. You live a fairly austere life, being a
  410.      poor college student. The only notable features are the bed
  411.      (unmade, of course) and a small wooden desk.  An exit is west. "
  412.     west = alley1                                   // room that lies west
  413.     out = alley1                                    // the exit
  414. ;
  415.  
  416. /*
  417.  *   The desk is a surface, which means you can put stuff on top of it.
  418.  *   Note that the drawer is a separate object.
  419.  */
  420. room3desk: surface, fixeditem
  421.     sdesc = "small wooden desk"
  422.     noun = 'desk'
  423.     adjective = 'small' 'wooden' 'wood'
  424.     location = startroom
  425.     ldesc =
  426.     {
  427.         "It's the small desk that comes with all of the rooms in the house.
  428.     The desktop is pitifully small, especially considering that you often
  429.     need to have several physics texts and tables of integrals open
  430.     simultaneously. The desk has a small drawer (";
  431.     if ( room3drawer.isopen ) "open"; else "closed";
  432.     "). ";
  433.     }
  434.     /*
  435.      *   For convenience, redirect any open/close activity to the
  436.      *   drawer.  Since the desk can't be opened and closed, we can
  437.      *   reasonably expect that the player is really referring to the
  438.      *   drawer if he tries to open or close the desk.
  439.      */
  440.     verDoOpen( actor ) = { room3drawer.verDoOpen( actor ); }
  441.     doOpen( actor ) = { room3drawer.doOpen( actor ); }
  442.     verDoClose( actor ) = { room3drawer.verDoClose( actor ); }
  443.     doClose( actor ) = { room3drawer.doClose( actor ); }
  444. ;
  445.  
  446. /*
  447.  *   A container can contain stuff.  An openable is a special type of container
  448.  *   that can be opened and closed.  Though it's technically part of the desk,
  449.  *   it's a fixeditem (==> it can't be taken), so we can just as well make it
  450.  *   part of startroom; note that this is in fact necessary, since if it were
  451.  *   located in the desk, it would appear to be ON the desk (since the desk is
  452.  *   a surface).
  453.  */
  454. room3drawer: openable, fixeditem
  455.     isopen = nil
  456.     sdesc = "drawer"
  457.     noun = 'drawer'
  458.     location = startroom
  459. ;
  460.  
  461. /*
  462.  *   A qcontainer is a "quiet container."  It acts like a container in all
  463.  *   ways, except that its contents aren't displayed in a room's message.
  464.  *   We want the player to have to think to examine the wastebasket more
  465.  *   carefully to find out what's in it, so we'll make it a qcontainer.
  466.  *   Which is fairly natural:  when looking around a room, you don't usually
  467.  *   notice what's in a waste basket, even though you may notice the waste
  468.  *   basket itself.
  469.  *
  470.  *   The sdesc is just the name of the object, as displayed by the game
  471.  *   (as in "You see a wastebasket here").  The noun and adjective lists
  472.  *   specify how the user can refer to the object; only enough need be
  473.  *   specified by the user to uniquely identify the object for the purpose
  474.  *   of the command.  Hence, you can specify as many words as you want without
  475.  *   adding any burden to the user---the more words the better.  The location
  476.  *   specifies the object (a room in this case) where the object is
  477.  *   to be found.
  478.  */
  479. wastebasket: qcontainer
  480.     sdesc = "waste basket"
  481.     noun = 'basket' 'wastebasket'
  482.     adjective = 'waste'
  483.     location = startroom
  484.     moveInto( obj ) =
  485.     {
  486.         /*
  487.      *   If this object is ever removed from its original location,
  488.      *   turn off the "quiet" attribute.
  489.      */
  490.         self.isqcontainer := nil;
  491.     pass moveInto;
  492.     }
  493. ;
  494.  
  495. /*
  496.  *   A beditem is something you can lie down on.
  497.  */
  498. bed: beditem
  499.     noun = 'bed'
  500.     location = startroom
  501.     ldesc = "It's a perfectly ordinary bed. It's particularly ordinary
  502.      (for around here, anyway) in that it hasn't been made in a very
  503.      long time. "
  504.     
  505.     /*
  506.      *   verDoLookunder is called when the player types "look under bed"
  507.      *   to verify that this object can be used as a direct object (Do) for
  508.      *   that verb (Lookunder).  If no message is printed, it means that
  509.      *   it can be used.
  510.      */
  511.     verDoLookunder( actor ) = {}
  512.     
  513.     /*
  514.      *   ...and then, if verification succeeded, doLookunder is called to
  515.      *   actually apply the verb (Lookunder) to this direct object (do).
  516.      */
  517.     doLookunder( actor ) =
  518.     {
  519.         if ( dollar.isfound )       // already found the dollar?
  520.         "You don't find anything of interest. ";
  521.     else
  522.     {
  523.         dollar.isfound := true;
  524.         "You find a dollar bill! You pocket the bill.
  525.         (Okay, so it's an obvious adventure game puzzle, but I'm sure
  526.         you would have been disappointed if nothing had been there.) ";
  527.         dollar.moveInto( Me );
  528.     }
  529.     }
  530.     
  531.     /*
  532.      *   Verification and action for the "Make" verb.
  533.      */
  534.     verDoMake( actor ) = {}
  535.     doMake( actor ) =
  536.     {
  537.         "It was a nice thought, but you suddenly realize that you never
  538.     learned how. ";
  539.     }
  540. ;
  541.  
  542. /*
  543.  *   We wish to add the verb "make."  We need to specify the sdesc (printed
  544.  *   by the system under certain circumstances), the vocabulary word itself
  545.  *   (as it will be entered by the user), and the suffix of the method that
  546.  *   will be called in direct objects.  By specifying a doAction of 'Make',
  547.  *   we are establishing that verDoMake and doMake messages will be sent to
  548.  *   the direct object of the verb.
  549.  */
  550. makeVerb: deepverb
  551.     sdesc = "make"
  552.     verb = 'make'
  553.     doAction = 'Make'
  554. ;
  555.  
  556. /*
  557.  *   An "item" is the most basic class of objects that a user can carry
  558.  *   around.  An item has no special properties.  The "iscrawlable"
  559.  *   attribute that we're setting here is used in the north-south crawl
  560.  *   in the steam tunnels (later in the game); setting it to "true"
  561.  *   means that the player can carry this object through the crawl.
  562.  */
  563. dollar: item
  564.     sdesc = "one dollar bill"
  565.     noun = 'bill'
  566.     adjective = 'dollar' 'one' '1'
  567.     iscrawlable = true
  568. ;
  569.  
  570. room4: room
  571.     sdesc = "Room 4"
  572.     ldesc = "This is room 4, where the weird senior across the hall
  573.      lives. An exit is to the east, and a strange passage leads down. "
  574.     east = alley1
  575.     out = alley1
  576.     down =
  577.     {
  578.         /*
  579.      *   This is a bit of code attached to a direction.  We can do
  580.      *   anything we want in code like this, so long as we return a
  581.      *   room (or nil) when we're done.  In this case, we just want
  582.      *   to display a message when the player travels this way.
  583.      */
  584.         "The passage takes you down a winding stairway to a previously
  585.     unseen entrance to...\b";
  586.         return( shiproom );
  587.     }
  588. ;
  589.  
  590. /*
  591.  *   A readable is an object that can be read, such as a note, a sign, a
  592.  *   book, or a memo.  By default, reading the object displays its ldesc.
  593.  *   However, if a separate readdesc is specified, "look at note" and
  594.  *   "read note" could display different messages.
  595.  */
  596. winNote: readable
  597.     iscrawlable = true
  598.     sdesc = "note"
  599.     ldesc = "Congratulations! You've broken the stack! Please take this
  600.      fine WarpMaster 2000(tm) warp motivator, with my compliments. I'll
  601.      see you in \"Deep Space Drifter\"! "
  602.     noun = 'note'
  603.     location = room4
  604. ;
  605.  
  606. shiproom: room
  607.     sdesc = "Spaceship Room"
  608.     ldesc = "This is a very large cave dominated by a tall spaceship.
  609.      High above, a vertical tunnel leads upward; it is evidently a launch
  610.      tube for the spaceship. The exit is north. "
  611.     north = chuteroom
  612.     in = shipinterior
  613.     up =
  614.     {
  615.         "The tunnel is far too high above to climb. ";
  616.     return( nil );
  617.     }
  618. ;
  619.  
  620. /*
  621.  *   The receptacle is both a fixeditem (something that can't be taken and
  622.  *   carried around) and a container, so both superclasses are specified.
  623.  */
  624. shiprecept: fixeditem, container
  625.     sdesc = "socket"
  626.     noun = 'socket'
  627.     location = shiproom
  628.     ioPutIn( actor, dobj ) =
  629.     {
  630.         /*
  631.      *   We only want to allow the warp motivator to be put in here.
  632.      *   Check any object going in and disallow it if it's anything else.
  633.      */
  634.         if ( dobj = motivator )
  635.     {
  636.         "It fits snugly. ";
  637.         dobj.moveInto( self );
  638.     }
  639.     else "It doesn't fit. ";
  640.     }
  641. ;
  642.  
  643. spaceship: fixeditem
  644.     sdesc = "spaceship"
  645.     noun = 'spaceship' 'ship'
  646.     adjective = 'space'
  647.     location = shiproom
  648.     ldesc =
  649.     {
  650.         "The spaceship is a tall gray metal cylinder with a pointed nosecone
  651.     high above, and three large fins at the bottom. A large socket ";
  652.     if ( motivator.location = shiprecept )
  653.         "on the side contains a warp motivator. ";
  654.     else
  655.         "is on the side (the socket is currently empty). The socket
  656.         is labelled \"insert warp motivator here.\" ";
  657.     "You can enter the spaceship through an open door. ";
  658.     }
  659.     verDoEnter( actor ) = {}
  660.     doEnter( actor ) = { self.doBoard( actor ); }
  661.     verDoBoard( actor ) = {}
  662.     doBoard( actor ) =
  663.     {
  664.         actor.travelTo( shipinterior );
  665.     }
  666. ;
  667.  
  668. shipinterior: room
  669.     sdesc = "Spaceship"
  670.     out = shiproom
  671.     ldesc = "You are in the cockpit of the spaceship. The control panel is
  672.      quite simple; the only feature that interests you at the moment is
  673.      a button labelled \"Launch.\" "
  674. ;
  675.  
  676. /*
  677.  *   This is a fake "ship" that the player can refer to while inside the
  678.  *   spaceship.  This allows commands such as "look at ship" and "get out"
  679.  *   to work properly while within the ship.
  680.  */
  681. shipship: fixeditem
  682.     location = shipinterior
  683.     sdesc = "spaceship"
  684.     noun = 'ship' 'spaceship'
  685.     adjective = 'space'
  686.     ldesc = { shipinterior.ldesc; }
  687.     verDoUnboard( actor ) = {}
  688.     doUnboard( actor ) =
  689.     {
  690.         Me.travelTo( shipinterior.out );
  691.     }
  692. ;
  693.  
  694. /*
  695.  *   A buttonitem can be pushed.  It's automatically a fixeditem, and
  696.  *   always defines the noun 'button'.  The doPush method specifies what
  697.  *   happens when the button is pushed.
  698.  */
  699. launchbutton: buttonitem
  700.     sdesc = "launch button"
  701.     adjective = 'launch'
  702.     location = shipinterior
  703.     doPush( actor ) =
  704.     {
  705.         if ( motivator.location = shiprecept )
  706.     {
  707.         incscore( 10 );
  708.         "The ship's engines start to come to life. \"Launch sequence
  709.         engaged,\" the mechanical computer voice announces. ";
  710.         if ( lloyd.location = Me.location )
  711.             "\n\tLloyd heads for the door. \"Sorry,\" he says, \"I can't
  712.         go with you. Your policy specifically excludes coverage
  713.         during missions in deep space, and, frankly, it's too risky
  714.         for my tastes. Besides, I don't appear in 'Deep Space
  715.         Drifter.'\" Lloyd waves goodbye, and rolls out of the
  716.         spaceship.\n\t";
  717.         "The hatch closes automatically, sealing you into the
  718.         space vessel. The engines become louder and louder.
  719.         The computer voice announces, \"Launch
  720.         in five... four... three... two... one... liftoff!\"
  721.         The engines blast the ship into orbit.
  722.         \n\tYou realize that the time has come to set course for
  723.         \"Deep Space Drifter,\" another fine TADS adventure from
  724.         High Energy Software.\b";
  725.         
  726.         scoreRank();
  727.         terminate();
  728.         quit();
  729.         abort;
  730.     }
  731.     else
  732.     {
  733.         "The ship's computer voice announces from a hidden speaker,
  734.         \"Error: no warp motivator installed.\" ";
  735.     }
  736.     }
  737. ;
  738.  
  739. motivator: treasure
  740.     sdesc = "warp motivator"
  741.     noun = 'motivator' 'warpmaster'
  742.     takevalue = 20
  743.     adjective = 'warp'
  744.     location = room4
  745.     ldesc = "It's a WarpMaster 2000(tm), the top-of-the-line model. "
  746. ;
  747.  
  748. foodthing: fooditem
  749.     noun = 'food'
  750.     sdesc = "food"
  751.     adesc = "some food"
  752.     ldesc = "It's a non-descript food item of the type the Food Service
  753.      typically prepares. "
  754.     location = room3drawer
  755. ;
  756.  
  757. /*
  758.  *   An openable is a container, with the additional property that it can
  759.  *   be opened and closed.  To simplify things, we don't have a separate
  760.  *   cap; use of the cap is implied in the "open" and "close" commands.
  761.  */
  762. bottle: openable
  763.     sdesc = "two-liter plastic bottle"
  764.     noun = 'bottle'
  765.     location = wastebasket
  766.     adjective = 'two-liter' 'plastic' 'two' 'liter'
  767.     isopen = nil
  768.     ldesc =
  769.     {
  770.         "The bottle is ";
  771.         if ( self.isfull ) "full of liquid nitrogen. ";
  772.     else "empty. ";
  773.  
  774.     "It's "; if ( self.isopen ) "open. "; else "closed. ";
  775.     
  776.     if ( funnel.location = self )
  777.         "There's a funnel in the bottle's mouth. ";
  778.     }
  779.     ioPutIn( actor, dobj ) =
  780.     {
  781.         if ( not self.isopen )
  782.     {
  783.         "It might help to open the bottle first. ";
  784.     }
  785.         else if ( dobj = ln2 )
  786.     {
  787.         if ( funnel.location = self )
  788.         {
  789.             "You manage to get some liquid nitrogen into the bottle. ";
  790.         bottle.isfull := true;
  791.         }
  792.         else
  793.         {
  794.             "You can't manage to get any liquid nitrogen into the
  795.              tiny opening. ";
  796.             }
  797.     }
  798.     else if ( dobj = funnel )
  799.     {
  800.         "A perfect fit! ";
  801.         funnel.moveInto( self );
  802.     }
  803.     else "That won't fit in the bottle. ";
  804.     }
  805.     verIoPourIn( actor ) = {}
  806.     ioPourIn( actor, dobj ) = { self.ioPutIn( actor, dobj ); }
  807.     doClose( actor ) =
  808.     {
  809.         if ( funnel.location = self )
  810.         "You'll have to take the funnel out first. ";
  811.     else if ( self.isfull )
  812.     {
  813.         "It takes some effort to close the bottle, since the rapidly
  814.         evaporating nitrogen occupies much more volume as a gas than
  815.         as a liquid. However, you manage to close it. ";
  816.         notify( self, #explodeWarning, 3 );
  817.         self.isopen := nil;
  818.     }
  819.     else
  820.     {
  821.         "Okay, it's closed. ";
  822.         self.isopen := nil;
  823.     }
  824.     }
  825.     
  826.     /*
  827.      *   explodeWarning is sent to the bottle as a "notification," which is
  828.      *   a message that's scheduled to occur some number of turns in the
  829.      *   future.  In this case, closing the bottle while it has liquid
  830.      *   nitrogen inside will set the explodeWarning notification.
  831.      */
  832.     explodeWarning =
  833.     {
  834.         if ( not self.isopen )
  835.     {
  836.         if ( self.isIn( Me.location ))
  837.         {
  838.             "\bThe bottle is starting to make lots of noise, as though
  839.             the plastic were being stretched to its limit. ";
  840.         }
  841.         notify( self, #explode, 3 );
  842.     }
  843.     }
  844.     
  845.     /*
  846.      *   explode is set as a notification by explodeWarning.  This routine
  847.      *   actually causes the explosion.  Since the bottle explodes, we will
  848.      *   remove it from the game (by moving it into "nil").  If the bottle
  849.      *   is in the right place, we'll also do some useful things.
  850.      */
  851.     explode =
  852.     {
  853.         if ( not self.isopen )
  854.     {
  855.         "\b";
  856.         if ( self.location = banksafe )
  857.         {
  858.             if ( Me.location = bankvault )
  859.         {
  860.             "There is a terrible explosion from within the safe.
  861.              The door blasts open with a clang and a huge cloud of
  862.              water vapor. ";
  863.              
  864.             if ( lloyd.location = bankvault )
  865.                 "\n\tLloyd throws himself between you and the
  866.             vault. \"Please be careful!\" he admonishes.
  867.             \"The payment for Accidental Death due to Explosion
  868.             is enormous!\" ";
  869.         }
  870.         else
  871.             "You hear a distant, muffled explosion. ";
  872.         
  873.         banksafe.isopen := true;
  874.         banksafe.isblasted := true;
  875.         }
  876.         else if ( self.isIn( Me.location ))
  877.         {
  878.             "The bottle explodes with a deafening boom and a huge
  879.             cloud of water vapor. As with most explosions, standing
  880.         in such close proximity was not advisable; it was, in
  881.         fact, fatal. ";
  882.         die();
  883.         abort;
  884.         }
  885.         else
  886.         {
  887.             "You hear a distant explosion. ";
  888.         }
  889.         
  890.         self.moveInto( nil );
  891.     }
  892.     }
  893. ;
  894.  
  895. /*
  896.  *   We're defining our own "class" of objects here.  Up to now, we've been
  897.  *   using classes defined in "adv.t", which you will recall we included at
  898.  *   the top of the file.  This class has some useful properties.  For one,
  899.  *   it has an attribute (istreasure) that tells us that the object is
  900.  *   indeed a treasure (used in the slot in room 4's door to ensure that
  901.  *   an object can be put in the slot).  In addition, it supplements the
  902.  *   doTake routine:  when a treasure is taken for the first time, we'll
  903.  *   add the object's "takevalue" to the overall score.
  904.  */
  905. class treasure: item
  906.     istreasure = true
  907.     takevalue = 5       // default point value when object is taken
  908.     putvalue = 5        // default point value when object is put in slot
  909.     doTake( actor ) =
  910.     {
  911.         if ( not self.hasScored )       // have we scored yet?
  912.     {
  913.         incscore( self.takevalue ); // add our "takevalue" to the score
  914.         self.hasScored := true;     // note that we have scored
  915.     }
  916.     pass doTake;        // continue with the normal doTake from "item"
  917.     }
  918. ;
  919.  
  920. alley1: room
  921.     sdesc = "Alley One"
  922.     ldesc =
  923.     {
  924.         "You are in the eternal twilight of Alley One, one of the twisty
  925.     little passages (all different) making up the student house in
  926.     which you live. Your room (room 3) is to the east. To the west
  927.     is a door (";
  928.     if ( alley1door.isopen ) "open"; else "closed";
  929.     "), affixed to which is a large sign. An exit is south, and the
  930.     hallway continues north. ";
  931.     }
  932.     east = startroom
  933.     north = alley1n
  934.     west =
  935.     {
  936.         /*
  937.      *   Sometimes, we'll want to run some code when the player walks
  938.      *   in a particular direction rather than just go to a new room.
  939.      *   This is how.  Returning "nil" means that the player can't go
  940.      *   this way.
  941.      */
  942.     if ( alley1door.isopen )
  943.     {
  944.         return( room4 );
  945.     }
  946.     else
  947.     {
  948.             "The door is closed and locked. You might read the
  949.         sign on the door for more information. ";
  950.         return( nil );
  951.     }
  952.     }
  953.     south = breezeway
  954.     out = breezeway
  955. ;
  956.  
  957. alley1n: room
  958.     sdesc = "Alley One"
  959.     ldesc = "You are at the north end of alley 1.  A small room is
  960.      to the west. "
  961.     south = alley1
  962.     west = alley1comp
  963. ;
  964.  
  965. alley1comp: room
  966.     sdesc = "Computer Room"
  967.     ldesc = 
  968.     {
  969.         "You are in a small computer room. Not surprisingly, the room
  970.          contains a personal computer. The exit is east. ";
  971.     if ( not self.isseen ) notify( compstudents, #converse, 0 );
  972.     }
  973.     east = alley1n
  974. ;
  975.  
  976. alley1pc: fixeditem
  977.     sdesc = "personal computer"
  978.     noun = 'computer'
  979.     adjective = 'personal'
  980.     location = alley1comp
  981.     ldesc = "The computer is in use by a couple of your fellow undergraduates.
  982.      Closer inspection of the screen shows that they seem to be playing a
  983.      text adventure. You've never really understood the appeal of those games
  984.      yourself, but you quickly surmise that the game is part of one of the
  985.      seniors' stacks. "
  986.     verIoTypeOn( actor ) = {}
  987.     ioTypeOn( actor, dobj ) =
  988.     {
  989.         "The computer is already in use. Common courtesy demands that you
  990.     wait your turn. ";
  991.     }
  992.     verDoTurnoff( actor ) = {}
  993.     doTurnoff( actor ) =
  994.     {
  995.         "The students won't let you, since they're busy using the computer. ";
  996.     }
  997. ;
  998.  
  999. compstudents: Actor
  1000.     location = alley1comp
  1001.     sdesc = "students"
  1002.     adesc = "a couple of students"
  1003.     ldesc = "The students are busy using the computer. "
  1004.     actorAction( v, d, p, i ) =
  1005.     {
  1006.         "They're too wrapped up in what they're doing. ";
  1007.     exit;
  1008.     }
  1009.     doAskAbout( actor, io ) =
  1010.     {
  1011.         "They're too busy to answer. ";
  1012.     }
  1013.     noun = 'students' 'undergraduates'
  1014.     actorDesc = "A couple of your fellow undergraduates are here, using
  1015.      the computer. They seem quite absorbed in what they're doing. "
  1016.     state = 0
  1017.     converse =
  1018.     {
  1019.         if ( Me.location = self.location )
  1020.     {
  1021.         "\b";
  1022.         if ( self.state = 0 )
  1023.             "\"Where are we going to find the dollar bill?\" one
  1024.         of the students asks the other. They sit back and stare
  1025.         at the screen, lost in thought. ";
  1026.         else if ( self.state = 1 )
  1027.             "\"Hey!\" says one of the students. \"Did you look under
  1028.         the bed?\" The other student shakes his head. \"No way,
  1029.         that would be a stupid puzzle!\" ";
  1030.         else if ( self.state = 2 )
  1031.             "One of the students using the computer types a long
  1032.         string of commands, and finally types \"look under bed.\"
  1033.         \"Wow! The dollar bill actually was under the bed! How
  1034.         lame!\" ";
  1035.         else
  1036.             "The students continue to play with the computer. ";
  1037.     
  1038.         self.state := self.state + 1;
  1039.     }
  1040.     }
  1041. ;
  1042.  
  1043. class lockedDoor: fixeditem, keyedLockable
  1044.     isopen = nil
  1045.     islocked = true
  1046.     noun = 'door'
  1047.     sdesc = "door"
  1048.     ldesc =
  1049.     {
  1050.         if ( self.isopen ) "It's open. ";
  1051.     else if ( self.islocked ) "It's closed and locked. ";
  1052.     else "It's closed. ";
  1053.     }
  1054.     verIoPutIn( actor ) = { "You can't put anything in that! "; }
  1055. ;
  1056.  
  1057. alley1door: lockedDoor
  1058.     location = alley1
  1059.     ldesc =
  1060.     {
  1061.         if ( self.isopen ) "It's open. ";
  1062.     else
  1063.             "The door is closed and locked. There is a slot in the door,
  1064.             and above that, a large sign is affixed to the door. ";
  1065.     }
  1066. ;
  1067.  
  1068. alley1sign: fixeditem, readable
  1069.     noun = 'sign'
  1070.     sdesc = "sign"
  1071.     location = alley1
  1072.     ldesc = "The sign says:
  1073.      \b\t\tWelcome to Ditch Day!
  1074.      \bThis stack is a treasure hunt. Gather all of the treasures, and you
  1075.      break the stack.
  1076.      To satisfy the requirements of this stack, you must find the
  1077.      items listed below, and deposit them in the slot in the door. When
  1078.      all items have been put in the slot, the stack will be solved and
  1079.      the door will open automatically. The items to find are:
  1080.      \b\tThe Great Seal of the Omega
  1081.      \n\tMr.\ Happy Gear
  1082.      \n\tA Million Random Digits
  1083.      \n\tA DarbCard
  1084.      \bThese items are hidden amongst the expanses of the Great
  1085.      Undergraduate Excavation project. Happy hunting!
  1086.      \bFor first-time participants, please note that
  1087.      this is a \"finesse stack.\" You are not permitted to attempt to break
  1088.      the stack by brute force. Instead, you must follow the rules above. "
  1089. ;
  1090.  
  1091. alley1slot: fixeditem, container
  1092.     noun = 'slot'
  1093.     sdesc = "slot"
  1094.     location = alley1
  1095.     itemcount = 0
  1096.     ioPutIn( actor, dobj ) =
  1097.     {
  1098.         if ( dobj.istreasure )
  1099.     {
  1100.         "\^<< dobj.thedesc >> disappears into the slot. ";
  1101.         dobj.moveInto( nil );
  1102.         incscore( dobj.putvalue );
  1103.         self.itemcount := self.itemcount + 1;
  1104.         if ( self.itemcount = 4 )
  1105.         {
  1106.             "As the treasure disappears into the slot, you hear a
  1107.         klaxon from the other side of the door. An elaborate
  1108.         series of clicks and clanks follows, then the door swings
  1109.         open. ";
  1110.         alley1door.islocked := nil;
  1111.         alley1door.isopen := true;
  1112.         }
  1113.     }
  1114.     else
  1115.     {
  1116.         "The slot will only accept items on the treasure list. ";
  1117.     }
  1118.     }
  1119. ;
  1120.  
  1121. breezeway: room
  1122.     sdesc = "Breezeway"
  1123.     ldesc = "You are in a short passage that connects a courtyard,
  1124.      to the east, to the outside of the building, which lies to the
  1125.      west. A hallway leads north. "
  1126.     north = alley1
  1127.     east = courtyard
  1128.     west = orangeWalk1
  1129. ;
  1130.  
  1131. courtyard: room
  1132.     sdesc = "Courtyard"
  1133.     ldesc = "You are in a large outdoor courtyard.
  1134.      An arched passage is to the west.
  1135.      A passage leads east, and a stairway leads down. "
  1136.     east = lounge
  1137.     down = hall1
  1138.     west = breezeway
  1139. ;
  1140.  
  1141. lounge: room
  1142.     sdesc = "Lounge"
  1143.     ldesc = "You are in the lounge. A passage leads west, and a dining
  1144.      room lies to the north. "
  1145.     north = diningRoom
  1146.     west = courtyard
  1147.     out = courtyard
  1148. ;
  1149.  
  1150. diningRoom: room
  1151.     sdesc = "Dining Room"
  1152.     ldesc = "You are in the dining room. There is a wooden table in
  1153.      the center of the room. The lounge lies to the south,
  1154.      and a passage to the east leads into the kitchen. "
  1155.     east = kitchen
  1156.     south = lounge
  1157. ;
  1158.  
  1159. diningTable: surface, fixeditem
  1160.     sdesc = "wooden table"
  1161.     noun = 'table'
  1162.     adjective = 'wooden'
  1163.     location = diningRoom
  1164. ;
  1165.  
  1166. fishfood: fooditem
  1167.     noun = 'module'
  1168.     adjective = 'fish' 'protein'
  1169.     sdesc = "fish protein module"
  1170.     ldesc = "It's a small pyramid-shaped white object, which is widely
  1171.      considered to consist primarily of fish protein. The food service
  1172.      typically resorts to such unappetizing fare toward the end of the
  1173.      year. "
  1174.     location = diningTable
  1175. ;
  1176.  
  1177. kitchen: room
  1178.     sdesc = "Kitchen"
  1179.     ldesc = "You are in the kitchen.  A ToxiCola(tm) machine is here.
  1180.      A passage leads into the dining room to the west. "
  1181.     west = diningRoom
  1182.     out = diningRoom
  1183. ;
  1184.  
  1185. toxicolaMachine: fixeditem, container
  1186.     noun = 'machine' 'compartment'
  1187.     adjective = 'toxicola'
  1188.     sdesc = "ToxiCola machine"
  1189.     ldesc =
  1190.     {
  1191.         "The machine dispenses ToxiCola, one of the big losers in the
  1192.          Cola Wars.  But, hey, it's cheap, so the food service installed it.
  1193.          The machine consists of a compartment large enough for a cup,
  1194.          and a button for dispensing ToxiCola into the cup. ";
  1195.      if ( cup.location = self )
  1196.         "The compartment contains a cup. ";
  1197.     }
  1198.     location = kitchen
  1199.     ioPutIn( actor, dobj ) =
  1200.     {
  1201.         if ( dobj <> cup )
  1202.         "That won't fit in the compartment. ";
  1203.     else pass ioPutIn;
  1204.     }
  1205. ;
  1206.  
  1207. cup: container
  1208.     sdesc = "coffee cup"
  1209.     noun = 'cup'
  1210.     adjective = 'coffee'
  1211.     isFull = nil
  1212.     ldesc =
  1213.     {
  1214.         if ( self.isFull ) "It's full of a viscous brown fluid. ";
  1215.     else "It's empty. ";
  1216.     }
  1217.     location = diningTable
  1218.     ioPutIn( actor, dobj ) =
  1219.     {
  1220.         if ( dobj = ln2 ) "The liquid nitrogen evaporates on contact. ";
  1221.     else "It won't fit in the cup. ";
  1222.     }
  1223. ;
  1224.  
  1225. toxicola: fixeditem
  1226.     sdesc = "toxicola"
  1227.     noun = 'toxicola' 'cola'
  1228.     ldesc = "It's a thick brown fluid. It appears to be quite flat. "
  1229.     doTake( actor ) =
  1230.     {
  1231.         "You'll have to leave it in the cup. ";
  1232.     }
  1233.     verDoDrink( actor ) = {}
  1234.     doDrink( actor ) =
  1235.     {
  1236.         "You drink the ToxiCola, despite your better judgment. It
  1237.     initially sparks a sugar and caffeine rush, but that rapidly
  1238.     fades, to be replaced by a strange dull throbbing. You enter
  1239.     a semi-conscious state for several hours. It finally passes,
  1240.     but you're not sure if it's been hours, weeks, or years. ";
  1241.     cup.isFull := nil;
  1242.     self.moveInto( nil );
  1243.     }
  1244. ;
  1245.  
  1246. toxicolaButton: buttonitem
  1247.     location = kitchen
  1248.     sdesc = "button"
  1249.     doPush( actor ) =
  1250.     {
  1251.         if ( cup.location = toxicolaMachine )
  1252.     {
  1253.         if ( cup.isFull )
  1254.             "ToxiCola spills over the already full cup, and drains
  1255.         away. ";
  1256.         else
  1257.         {
  1258.             "The horrible brown viscous fluid you have come to
  1259.         know as ToxiCola fills the cup. ";
  1260.         cup.isFull := true;
  1261.         toxicola.moveInto( cup );
  1262.         }
  1263.     }
  1264.     else
  1265.     {
  1266.         "Horrible viscous brown fluid spills into the empty
  1267.         compartment, and drains away. ";
  1268.     }
  1269.     }
  1270. ;
  1271.  
  1272. orangeWalk1: room
  1273.     sdesc = "Orange Walk"
  1274.     ldesc = "You are on a walkway lined with orange trees. The walkway
  1275.      continues to the north, and an arched passage leads into a building
  1276.      to the east. "
  1277.     east = breezeway
  1278.     north = orangeWalk2
  1279. ;
  1280.  
  1281. /*
  1282.  *   We want a "class" of objects for the orange trees lining the
  1283.  *   orange walk.  They don't do anything, so they're "decoration."
  1284.  */
  1285. class orangeTree: decoration
  1286.     sdesc = "orange trees"
  1287.     ldesc = "The orange trees are perfectly ordinary. "
  1288.     adesc = "an orange tree"
  1289.     noun = 'tree' 'trees'
  1290.     adjective = 'orange'
  1291.     verDoClimb( actor ) = {}
  1292.     doClimb( actor ) =
  1293.     {
  1294.         "You climb into one of the orange trees, and quickly find the
  1295.     view from the few feet higher to be highly uninteresting. You
  1296.     soon climb back down. ";
  1297.     }
  1298. ;
  1299.  
  1300. orangeTree1: orangeTree
  1301.     location = orangeWalk1
  1302. ;
  1303.  
  1304. orangeWalk2: room
  1305.     sdesc = "Orange Walk"
  1306.     ldesc = "You are on a walkway lined with orange trees. The walkway
  1307.      continues to the south, and leads into a large grassy square to the
  1308.      north. "
  1309.     north = quad
  1310.     south = orangeWalk1
  1311. ;
  1312.  
  1313. orangeTree2: orangeTree
  1314.     location = orangeWalk2
  1315. ;
  1316.  
  1317. quad: room
  1318.     sdesc = "Quad"
  1319.     ldesc = "You are on the quad, a large grassy square in the
  1320.      center of campus.  The bookstore lies to the northwest; the
  1321.      health center lies to the northeast; Buildings and Grounds
  1322.      lies to the north; and walkways lead west and south.
  1323.      \n\tSome students dressed in radiation suits are staging a bogus
  1324.      toxic leak, undoubtedly to fulfill the requirements of one of the
  1325.      stacks.  They are wandering around, looking very busy.  Many reporters
  1326.      are standing at a safe distance, looking terrified.
  1327.      The supposed clean-up crew is pouring lots of liquid nitrogen onto
  1328.      the ground, resulting in huge clouds of water vapor. "
  1329.     south = orangeWalk2
  1330.     nw = bookstore
  1331.     west = walkway
  1332.     ne = healthCenter
  1333.     north = BandG
  1334. ;
  1335.  
  1336. BandG: room
  1337.     sdesc = "B&G"
  1338.     ldesc = "You are in the Buildings and Grounds office. The exit is to
  1339.      the south. "
  1340.     south = quad
  1341.     out = quad
  1342. ;
  1343.  
  1344. bngmemo: readable
  1345.     sdesc = "scrap of paper"
  1346.     iscrawlable = true
  1347.     noun = 'scrap' 'paper'
  1348.     location = BandG
  1349.     ldesc = "Most of the paper has been torn away; the part that remains
  1350.      seems to have a list of numerical codes of some kind on it:
  1351.      \b\t293 -- north tunnel lighting
  1352.      \n\t322 -- station 2 lighting
  1353.      \n\t612 -- behavior lab
  1354.      \bThe rest is missing. "
  1355. ;
  1356.  
  1357. healthCenter: room
  1358.     sdesc = "Health Center"
  1359.     ldesc = "You are in the health center. Like the rest of campus, this
  1360.      place is deserted because of Ditch Day. The large desk would normally
  1361.      have a receptionist behind it, but today, no one is in sight. "
  1362.     sw = quad
  1363.     out = quad
  1364. ;
  1365.  
  1366. healthDesk: fixeditem, surface
  1367.     sdesc = "desk"
  1368.     noun = 'desk'
  1369.     adjective = 'large'
  1370.     location = healthCenter
  1371. ;
  1372.  
  1373. healthMemo: readable
  1374.     sdesc = "health memo"
  1375.     iscrawlable = true
  1376.     noun = 'memo'
  1377.     plural = 'memos'
  1378.     adjective = 'health'
  1379.     location = healthDesk
  1380.     ldesc =
  1381.        "From:\t\tDirector of the Health Center
  1382.       \nTo:\t\tAll Health Center Personnel
  1383.       \nSubject:\tToxiCola toxicity
  1384.       \bMany students have visited the Health Center recently, complaining
  1385.       that the ToxiCola that is served in the student houses has not been
  1386.       properly caffeinated.  The students are complaining of drowsiness,
  1387.       dizziness, and other symptoms that are normally associated with an
  1388.       insufficient intake of caffeine.
  1389.       \n\tUpon investigation, we have learned that the ToxiCola dispensers
  1390.       in the student houses have become contaminated with a substance that
  1391.       induces these effects. The substance has not yet been identified, but
  1392.       the concentration seems to be increasing. All Health Center personnel
  1393.       are urgently directed to advise students to avoid the ToxiCola if at
  1394.       all possible. Students should be informed that their student health
  1395.       insurance coverage will cover any purchases of other caffeinated
  1396.       beverages that they need for their studies. "
  1397. ;
  1398.  
  1399. students: decoration
  1400.     sdesc = "students"
  1401.     adesc = "a group of students"
  1402.     noun = 'student' 'students'
  1403.     location = quad
  1404.     ldesc = "The students are making quite a good show of the simulated
  1405.      nuclear waste spill. They're all wearing white clean-room suits with
  1406.      official-looking \"Radiation Control District\" badges. They're
  1407.      scampering about purposefully, keeping the crowd of reporters back
  1408.      at a safe distance. "
  1409. ;
  1410.  
  1411. presscorp: decoration
  1412.     sdesc = "reporters"
  1413.     adesc = "a group of reporters"
  1414.     noun = 'reporter' 'reporters'
  1415.     location = quad
  1416. ;
  1417.  
  1418. flask: container
  1419.     sdesc = "flask"
  1420.     ldesc = "The flask appears to have lots of liquid nitrogen in it;
  1421.      it's hard to tell just how much, since the opening is perpetually
  1422.      clouded over with thick plumes of water vapor. "
  1423.     noun = 'flask'
  1424.     location = quad
  1425.     ioPutIn( actor, dobj ) =
  1426.     {
  1427.         "You know from experience that it wouldn't be a good idea to
  1428.     put "; dobj.thedesc; " into the liquid nitrogen, since the LN2 is
  1429.     really, really cold. ";
  1430.     }
  1431. ;
  1432.  
  1433. pourVerb: deepverb
  1434.     sdesc = "pour"
  1435.     verb = 'pour'
  1436.     doAction = 'Pour'
  1437.     ioAction( inPrep ) = 'PourIn'
  1438.     ioAction( onPrep ) = 'PourOn'
  1439. ;
  1440.  
  1441. ln2: item
  1442.     sdesc = "liquid nitrogen"
  1443.     adesc = "some liquid nitrogen"      // "a liquid nitrogen" doesn't compute
  1444.     ldesc = "You can't see much, thanks to the thick clouds of water
  1445.      vapor that inevitably form over such a cold substance. "
  1446.     noun = 'nitrogen' 'ln2'
  1447.     adjective = 'liquid'
  1448.     location = flask
  1449.     doTake( actor ) =
  1450.     {
  1451.         "You're better off leaving the liquid nitrogen in the flask. ";
  1452.     }
  1453.     verDoPour( actor ) = {}
  1454.     verDoPourIn( actor, io ) = {}
  1455.     doPour( actor ) =
  1456.     {
  1457.         askio( inPrep );
  1458.     }
  1459. ;
  1460.  
  1461. walkway: room
  1462.     sdesc = "Walkway"
  1463.     ldesc = "You are on a walkway.  A large grassy square lies to the east;
  1464.      buildings lie to the north and south. The walkway continues west. "
  1465.     east = quad
  1466.     north = behaviorLab
  1467.     south = security
  1468.     west = walkway2
  1469. ;
  1470.  
  1471. walkway2: room
  1472.     sdesc = "Walkway"
  1473.     ldesc = "You are on a walkway, which continues to the east. Buildings
  1474.      are to the north and south. "
  1475.     east = walkway
  1476.     south = explosiveLab
  1477.     north = biobuilding
  1478. ;
  1479.  
  1480. biobuilding: room
  1481.     sdesc = "Biology Building"
  1482.     ldesc = "You are in the biology building. The exit is south. "
  1483.     south = walkway2
  1484.     out = walkway2
  1485. ;
  1486.  
  1487. bionotes: readable
  1488.     sdesc = "notebook"
  1489.     location = biobuilding
  1490.     noun = 'notebook'
  1491.     ldesc = "The notebook explains various lab techniques used in cloning
  1492.      organisms. Since the invention of the CloneMaster, which requires only
  1493.      a sample of genetic material from a subject (such as some blood, or a
  1494.      bit of skin, or the like) and the basic skills required to operate a
  1495.      household blender, most of the techniques are obsolete. Some of the data,
  1496.      however, are interesting. For example, the notebook outlines the procedure
  1497.      for reversing the sex of a clone; the introduction of chemicals identified
  1498.      herein only as Genetic Factor XQ3, Polymerase Blue, and Compound T99 at
  1499.      the start of the cloning process aparently does the trick. Most of the
  1500.      rest of the document is a discussion of the human immune system; the
  1501.      author comes to the conclusion that the human immune system, though a
  1502.      novel idea, is far too improbable to ever actually be implemented. "
  1503. ;
  1504.  
  1505. explosiveLab: room
  1506.     sdesc = "Explosive Lab"
  1507.     ldesc = "It's not that the lab itself is explosive (though it has blown
  1508.      up a couple times in the past); rather, they study explosives here.
  1509.      Unfortunately, all the good stuff has been removed by other Ditch Day
  1510.      participants who got up earlier than you did. The exit is north. "
  1511.     north = walkway2
  1512.     out = walkway2
  1513. ;
  1514.  
  1515. ln2doc: readable
  1516.     sdesc = "thesis"
  1517.     noun = 'thesis'
  1518.     location = explosiveLab
  1519.     ldesc = "The thesis is about Thermal Expansion Devices. It explains about
  1520.      a new class of explosives that are made possible by low-temperature
  1521.      fluid technology (i.e., liquid nitrogen) and high-tension polymer
  1522.      containment vessels (i.e., plastic bottles). A great deal of jargon and
  1523.      complicated theories are presented, presumably to fool the faculty
  1524.      advisor into thinking the author actually did something useful with his
  1525.      research funds; after wading through the nonsense, you find that the
  1526.      paper is merely talking about putting liquid nitrogen into a plastic
  1527.      soft-drink bottle, closing the bottle, then letting nature take its
  1528.      course. Since the nitrogen will tend to evaporate at room temperature,
  1529.      but will have no place to go, the bottle will eventually explode.
  1530.      \bOn the cover page, you notice this important warning: \"Kids! Don't
  1531.      try this at home! Liquid nitrogen is extremely cold, and can cause severe
  1532.      injuries; it should only be handled by trained professionals. Never
  1533.      put liquid nitrogen in a closed container.\" "
  1534. ;
  1535.  
  1536. bookstore: room
  1537.     sdesc = "Bookstore"
  1538.     ldesc = "You are in the bookstore. The shelves are quite empty; no doubt
  1539.      everything has been bought up by seniors in attempts to build their
  1540.      stacks and underclassmen in attempts to break them. The exit is to the
  1541.      southeast. "
  1542.     out = { return( self.se ); }
  1543.     se =
  1544.     {
  1545.         /*
  1546.      *   We need to check that the battery has been paid for, if it's
  1547.      *   been taken.  If not, don't let 'em out.
  1548.      */
  1549.         if ( battery.isIn( Me ) and not battery.isPaid )
  1550.     {
  1551.         "The clerk notices that you want to buy the battery. \"That'll be
  1552.         five dollars,\" she says, waiting patiently. ";
  1553.         return( nil );
  1554.     }
  1555.     else return( quad );
  1556.     }
  1557. ;
  1558.  
  1559. battery: item
  1560.     location = bookstore
  1561.     isPaid = nil
  1562.     sdesc = "battery"
  1563.     noun = 'battery'
  1564.     verDoPayfor( actor ) =
  1565.     {
  1566.         if ( actor.location <> bookstore )
  1567.         "I don't see anyone to pay! ";
  1568.     }
  1569.     doPayfor( actor ) =
  1570.     {
  1571.         clerk.doPay( actor );
  1572.     }
  1573.     verIoPayFor( actor ) = {}
  1574.     ioPayFor( actor, dobj ) =
  1575.     {
  1576.         if ( dobj <> clerk )
  1577.     {
  1578.         "You can't pay "; dobj.thedesc; " for that! ";
  1579.     }
  1580.     else clerk.doPay( actor );
  1581.     }
  1582. ;
  1583.  
  1584. forPrep: Prep
  1585.     sdesc = "for"
  1586.     preposition = 'for'
  1587. ;
  1588.  
  1589. payVerb: deepverb
  1590.     sdesc = "pay"
  1591.     verb = 'pay'
  1592.     doAction = 'Pay'
  1593.     ioAction( forPrep ) = 'PayFor'
  1594. ;
  1595.  
  1596. payforVerb: deepverb
  1597.     verb = 'pay for'
  1598.     sdesc = "pay for"
  1599.     doAction = 'Payfor'
  1600. ;
  1601.  
  1602. money: item
  1603.     sdesc = "five dollar bill"
  1604.     noun = 'bill' 'money'
  1605.     adjective = 'five' 'dollar' '5'
  1606.     iscrawlable = true
  1607. ;
  1608.  
  1609. clerk: Actor
  1610.     noun = 'clerk'
  1611.     location = bookstore
  1612.     sdesc = "Clerk"
  1613.     isHer = true
  1614.     ldesc = "The clerk is a kindly lady to whom you have paid many hundreds
  1615.      of dollars for books and other college necessities. "
  1616.     actorDesc = "A clerk is near the exit, prepared to ring up any purchases
  1617.      you might want to make (not that there's much left here to buy). "
  1618.     verIoGiveTo( actor ) = {}
  1619.     ioGiveTo( actor, dobj ) =
  1620.     {
  1621.         if ( dobj = money or dobj = dollar ) self.doPay( actor );
  1622.     else if ( dobj = darbcard )
  1623.     {
  1624.         "The clerk shakes her head. \"Sorry,\" she says, \"we only
  1625.         accept cash.\" ";
  1626.     }
  1627.     else if ( dobj = cup and cup.isFull )
  1628.     {
  1629.         "\"I never drink that stuff,\" the clerk says, \"and neither
  1630.         should you! Do you have any idea what's in there? I probably
  1631.         don't know half as much chemistry as you, but I know better
  1632.         than to drink that.\" ";
  1633.     }
  1634.     else
  1635.     {
  1636.         "She doesn't appear interested. ";
  1637.     }
  1638.     }
  1639.     verDoPay( actor ) = {}
  1640.     doPay( actor ) =
  1641.     {
  1642.         if ( not battery.isIn( Me ))
  1643.     {
  1644.         "The clerk looks confused. \"I don't see what you're
  1645.         paying for,\" she says. She then looks amused, realizing
  1646.         that the students here somtimes get a little ahead of
  1647.         themselves. ";
  1648.     }
  1649.     else if ( battery.isPaid )
  1650.     {
  1651.         "The clerk looks confused and says, \"You've already paid!\"
  1652.         She then looks amused, realizing that the students here can
  1653.         be a bit absent-minded at times. ";
  1654.     }
  1655.         else if ( not money.isIn( Me ))
  1656.     {
  1657.         if ( dollar.isIn( Me ))
  1658.         {
  1659.             "The clerk reminds you that the battery is five dollars.
  1660.         All you have is one dollar. She looks amused; \"They can
  1661.         do calculus in their sleep but they can't add,\" she jokes. ";
  1662.         }
  1663.         else
  1664.         {
  1665.             "You unfortunately don't have anything with which to pay the
  1666.             clerk. ";
  1667.         }
  1668.     }
  1669.     else
  1670.     {
  1671.         "The clerk accepts your money and says \"Thank you, have a nice
  1672.         day.\"";
  1673.         battery.isPaid := true;
  1674.         money.moveInto( nil );
  1675.     }
  1676.     }
  1677. ;
  1678.  
  1679. behaviorLab: room
  1680.     sdesc = "Behavior Lab"
  1681.     ldesc = "You are in the behavior lab.  The exit is to the south,
  1682.      and a locked door is to the north. The door is labelled \"Maze -
  1683.      Experimental Subjects Only.\" In addition, a passage labelled
  1684.      \"Viewing Room\" leads east. "
  1685.     south = walkway
  1686.     out = walkway
  1687.     east = mazeview
  1688.     north =
  1689.     {
  1690.         "The door is closed and locked. Besides, do you really want to
  1691.     be an \"Experimental Subject\"?";
  1692.     return( nil );
  1693.     }
  1694. ;
  1695.  
  1696. mazeview: room
  1697.     sdesc = "Maze Viewing Room"
  1698.     ldesc =
  1699.     {
  1700.         "The entire north wall of this room is occupied by a window
  1701.          overlooking a vast human-sized labyrinth. No experimental subjects
  1702.          (i.e., students) seem to be wandering through the maze at the
  1703.      moment, ";
  1704.      
  1705.     if ( not mazeStart.isseen )
  1706.         "but you have the strange feeling that you will have to find
  1707.         your way through the maze some day. You read with a sense of
  1708.         foreboding the plaque affixed to the wall:\b";
  1709.     else
  1710.             "so your attention wanders to the plaque on the wall:\b";
  1711.         
  1712.         mazeplaque.ldesc;
  1713.     }
  1714.     west = behaviorLab
  1715. ;
  1716.  
  1717. mazewindow: fixeditem
  1718.     sdesc = "window"
  1719.     noun = 'window'
  1720.     location = mazeview
  1721.     verDoLookthru( actor ) = {}
  1722.     doLookthru( actor ) = { self.ldesc; }
  1723.     ldesc =
  1724.     {
  1725.         "The window looks out onto a vast human-sized labyrinth.
  1726.          The maze is currently devoid of experimental subjects";
  1727.     if ( not mazeStart.isseen )
  1728.         ", but you have the strange feeling that you'll have to find
  1729.         your way through the maze someday";
  1730.     ". ";
  1731.     }
  1732. ;
  1733.  
  1734. mazeplaque: fixeditem, readable
  1735.     sdesc = "plaque"
  1736.     noun = 'plaque'
  1737.     location = mazeview
  1738.     ldesc = "*** The Behavioral Biology Laboratory Psycho-Magnetic Maze ***
  1739.      \bThe Psycho-Magnetic Maze that is visible through the window has been
  1740.      constructed to determine how the human directional sense interacts with
  1741.      strong electromagnetic and nuclear fields. Through careful tuning of
  1742.      these fields, we have found that human subjects often become completely
  1743.      disoriented in the maze, resulting in hours of random and
  1744.      desperate wandering, and much amusement to those of us in the observation
  1745.      room. "
  1746. ;
  1747.  
  1748. behaviorDoor: lockedDoor
  1749.     ldesc = "The door is closed and locked, and labelled \"Experimental
  1750.      Subjects Only.\""
  1751.     location = behaviorLab
  1752. ;
  1753.  
  1754. security: room
  1755.     sdesc = "Security Office"
  1756.     ldesc = "You are in the campus security office, the very nerve-center of
  1757.      the elite Kaltech Kops.  The officers all
  1758.      appear to be absent; undoubtedly they are all scurrying hither and
  1759.      yon trying to deal with the ditch-day festivities.  There is a desk
  1760.      in the center of the room.  The exit is to
  1761.      the north. "
  1762.     north = walkway
  1763.     out = walkway
  1764. ;
  1765.  
  1766. securityDesk: fixeditem, surface
  1767.     sdesc = "desk"
  1768.     noun = 'desk'
  1769.     location = security
  1770. ;
  1771.  
  1772. securityMemo: readable
  1773.     sdesc = "security memo"
  1774.     iscrawlable = true
  1775.     noun = 'memo'
  1776.     plural = 'memos'
  1777.     adjective = 'security'
  1778.     location = securityDesk
  1779.     ldesc =
  1780.        "From:\t\tDirector of Security
  1781.       \nTo:\t\tAll Security Personnel
  1782.       \nSubject:\tGreat Undergraduate Excavation
  1783.       \bIt has come to the attention of the Kaltech Kops that the student
  1784.       activity in the steam tunnels, known as the \"Great Undergraduate
  1785.       Excavation\" project, has escalated vastly in recent years. Due to
  1786.       objections from city officials about noise from underground and the
  1787.       fear local residents have expressed that their property will be
  1788.       undermined, this office has taken action to halt all GUE activity.
  1789.       Effective immediately, a security officer will be posted at all
  1790.       known steam tunnel entrances, and shall under no circumstances allow
  1791.       students to enter. "
  1792. ;
  1793.  
  1794. flashlight: container, lightsource
  1795.     sdesc = "flashlight"
  1796.     noun = 'flashlight' 'light'
  1797.     adjective = 'flash'
  1798.     location = security
  1799.     ioPutIn( actor, dobj ) =
  1800.     {
  1801.         if ( dobj <> battery )
  1802.     {
  1803.         "You can't put "; dobj.thedesc; " into the flashlight. ";
  1804.     }
  1805.     else pass ioPutIn;
  1806.     }
  1807.     Grab( obj ) =
  1808.     {
  1809.         /*
  1810.      *   Grab( obj ) is invoked whenever an object 'obj' that was
  1811.      *   previously located within me is removed.  If the battery is
  1812.      *   removed, the flashlight turns off.
  1813.      */
  1814.         if ( obj = battery ) self.islit := nil;
  1815.     }
  1816.     ldesc =
  1817.     {
  1818.         if ( battery.location = self )
  1819.     {
  1820.         if ( self.islit )
  1821.             "The flashlight (which contains a battery) is turned on
  1822.         and is providing a warm, reassuring beam of light. ";
  1823.         else
  1824.             "The flashlight (which contains a battery) is currently off. ";
  1825.     }
  1826.     else
  1827.     {
  1828.         "The flashlight is off. It seems to be missing a battery. ";
  1829.     }
  1830.     }
  1831.     verDoTurnon( actor ) =
  1832.     {
  1833.         if ( self.islit ) "It's already on! ";
  1834.     }
  1835.     doTurnon( actor ) =
  1836.     {
  1837.         if ( battery.location = self )
  1838.     {
  1839.         "The flashlight is now on. ";
  1840.         self.islit := true;
  1841.     }
  1842.     else "The flashlight won't turn on without a battery. ";
  1843.     }
  1844.     verDoTurnoff( actor ) =
  1845.     {
  1846.         if ( not self.islit ) "It's not on. ";
  1847.     }
  1848.     doTurnoff( actor ) =
  1849.     {
  1850.         "Okay, the flashlight is now turned off. ";
  1851.     self.islit := nil;
  1852.     }
  1853. ;
  1854.  
  1855. goToSleep: function
  1856. {
  1857. }
  1858.  
  1859. hall1: room
  1860.     sdesc = "Hallway"
  1861.     ldesc = "You are at the west end of a basement hallway. A stairway
  1862.      leads up. "
  1863.     up = courtyard
  1864.     east = hall2
  1865. ;
  1866.  
  1867. hall2: room
  1868.     sdesc = "Hallway"
  1869.     ldesc = "You are in an east-west hallway in the basement.  Another hallway
  1870.      goes off to the north. "
  1871.     west = hall1
  1872.     east = hall3
  1873.     north = hall4
  1874. ;
  1875.  
  1876. hall3: room
  1877.     sdesc = "Hallway"
  1878.     ldesc = "You are at the east end of a hallway in the basement.
  1879.      A passage leads north. "
  1880.     west = hall2
  1881.     north = laundry
  1882. ;
  1883.  
  1884. laundry: room
  1885.     sdesc = "Laundry Room"
  1886.     ldesc = "You are in the laundry room. There is a washing machine
  1887.      against one wall. The exit is to the south. "
  1888.     south = hall3
  1889.     out = hall3
  1890. ;
  1891.  
  1892. washingMachine: fixeditem, openable
  1893.     sdesc = "washing machine"
  1894.     isopen = nil
  1895.     location = laundry
  1896.     noun = 'machine' 'washer'
  1897.     adjective = 'washing'
  1898. ;
  1899.  
  1900. jeans: item
  1901.     sdesc = "blue jeans"
  1902.     location = washingMachine
  1903.     noun = 'jeans' 'pants'
  1904.     adjective = 'blue'
  1905.     ldesc =
  1906.     {
  1907.         if ( self.isseen ) "It's an ordinary pair of jeans. ";
  1908.     else
  1909.     {
  1910.         "It looks like an ordinary pair of jeans, though not
  1911.         your size. As you inspect them, you notice a key fall
  1912.         out of them and to the ground. ";
  1913.         masterKey.moveInto( Me.location );
  1914.         self.isseen := true;
  1915.     }
  1916.     }
  1917.     verDoLookin( actor ) = {}
  1918.     doLookin( actor ) = { self.ldesc; }
  1919.     verDoWear( actor ) = { "They're not your size. "; }
  1920. ;
  1921.  
  1922. masterKey: keyItem
  1923.     iscrawlable = true
  1924.     sdesc = "master key"
  1925.     noun = 'key'
  1926.     adjective = 'master'
  1927.     doTake( actor ) =
  1928.     {
  1929.         if ( not self.isseen )
  1930.     {
  1931.         "*Some* adventure games would try to impose their authors'
  1932.         misguided sense of ethics on you at this point, telling you
  1933.         that you don't feel like picking up the key, or you don't have
  1934.         time to do that, or that it's against the rules to even possess
  1935.         a master key, much less steal one from some other student's
  1936.         pants that you happened to find in a laundry, or even more
  1937.         likely that you are unable to take the key while wearing that
  1938.         dress. However, you're the player, and you're in charge around
  1939.         here, so I'll let you make your own judgments about what's
  1940.         ethical and proper here... ";
  1941.         self.isseen := true;
  1942.     }
  1943.     pass doTake;
  1944.     }
  1945. ;
  1946.  
  1947. hall4: room
  1948.     sdesc = "Hallway"
  1949.     ldesc = "You are in a north-south hallway in the basement. "
  1950.     south = hall2
  1951.     north = hall5
  1952. ;
  1953.  
  1954. hall5: room
  1955.     sdesc = "Hallway"
  1956.     ldesc = "You are at a corner in the basement hallway. You can go east
  1957.      or south. "
  1958.     south = hall4
  1959.     east = hall6
  1960. ;
  1961.  
  1962. hall6: room
  1963.     sdesc = "Hallway"
  1964.     ldesc = "You are at the east end of a basement hallway. To the north is
  1965.      a \"storage room,\" which everyone knows is actually an entrance
  1966.      to the steam tunnels. "
  1967.     west = hall5
  1968.     north = storage
  1969. ;
  1970.  
  1971. storage: room
  1972.     sdesc = "Storage Room"
  1973.     ldesc =
  1974.     {
  1975.         "You are in a large storage room. There really hasn't been
  1976.          anything stored here for a long time (at least, not anything that
  1977.          anybody wants to ever see again). The exit is to the south. To
  1978.      the north lies a door, which is ";
  1979.      if ( tunnelDoor.isopen ) "open"; else "closed"; ". A small card
  1980.      table is sitting in front of the door. ";
  1981.     }
  1982.     south = hall6
  1983.     north =
  1984.     {
  1985.         if ( guard.isActive )
  1986.     {
  1987.         "The guard won't let you enter the tunnel. ";
  1988.             return( nil );
  1989.     }
  1990.     else if ( not tunnelDoor.isopen )
  1991.     {
  1992.         "A closed door stands in your way. ";
  1993.         setit( tunnelDoor );       /* "it" now refers to the closed door */
  1994.         return( nil );
  1995.     }
  1996.     else return( tunnel1 );
  1997.     }
  1998.     enterRoom( actor ) =
  1999.     {
  2000.         if ( guard.isActive )
  2001.     {
  2002.         notify( guard, #patrol, 0 );
  2003.     }
  2004.     pass enterRoom;
  2005.     }
  2006.     leaveRoom( actor ) =
  2007.     {
  2008.         if ( guard.isActive )
  2009.     {
  2010.         unnotify( guard, #patrol );
  2011.     }
  2012.     pass leaveRoom;
  2013.     }
  2014. ;
  2015.  
  2016. tunnelDoor: lockedDoor
  2017.     location = storage
  2018.     mykey = masterKey
  2019. ;
  2020.  
  2021. guard: Actor
  2022.     sdesc = "guard"
  2023.     noun = 'guard' 'him'
  2024.     isHim = true
  2025.     ldesc =
  2026.     {
  2027.         "The guard is a member of the Kaltech Kops, the elite corps of
  2028.     dedicated men and women that keeps the campus safe from undesirables
  2029.     (i.e., the students). ";
  2030.     if ( not self.isActive )
  2031.         "Currently, the guard is fast asleep, which is quite typical. ";
  2032.     }
  2033.     adjective = 'security'
  2034.     isActive = true
  2035.     location = storage
  2036.     actorDesc =
  2037.     {
  2038.     if ( self.isActive )
  2039.         "A guard is sitting at the card table in front of the door.
  2040.         He watches you carefully, evidently thinking that you might
  2041.         be planning to try to go through the door. ";
  2042.     else
  2043.         "A guard is slumped over a small card table in front of the
  2044.         steam tunnel entrance, evidently fast asleep. How typical. ";
  2045.     }
  2046.     verIoGiveTo( actor ) =
  2047.     {
  2048.         if ( not self.isActive )
  2049.         "The guard appears to be fast asleep. ";
  2050.     }
  2051.     ioGiveTo( actor, dobj ) =
  2052.     {
  2053.         if ( dobj = dollar or dobj = money )
  2054.         "The guard looks at you sternly. \"You should be ashamed of
  2055.         yourself, trying to bribe a member of the elite Kaltech Kops!\"
  2056.         he admonishes you, refusing your offer. ";
  2057.         else if ( dobj <> cup or not cup.isFull )
  2058.         "The guard doesn't appear interested. ";
  2059.     else
  2060.     {
  2061.         self.isActive := nil;
  2062.         unnotify( self, #patrol );
  2063.         "The guard happily accepts your offer; \"ToxiCola! My favorite!\"
  2064.         he says appreciatively, not knowing the evil deed
  2065.         that you have in mind. He quickly drinks the entire cup of
  2066.         ToxiCola. \"Wow! Just the caffeine pickup I needed,\" he says
  2067.         happily.
  2068.         \n\tAfter a few moments, though, he looks rather queasy. \"That
  2069.         caffeine just doesn't last long enough,\" he says just before
  2070.         he passes out, slumping over the card table. ";
  2071.         cup.isFull := nil;
  2072.         toxicola.moveInto( nil );
  2073.         cup.moveInto( cardtable );
  2074.         incscore( 10 );
  2075.     }
  2076.     }
  2077.     patrolMessage =
  2078.     [
  2079.         // random message 1
  2080.     'The guard eyes you warily.'
  2081.     // random message 2
  2082.     'The guard looks at his empty glass, probably wishing he had
  2083.     something to drink.'
  2084.     // random message 3
  2085.     'The guard flips purposefully through the pages of his memo pad.'
  2086.     // random message 4
  2087.     'The guard writes something down on his memo pad, glancing up from
  2088.     time to time to eye you suspiciously.'
  2089.     // random message 5
  2090.     'The guard picks up his empty glass and starts to drink, then
  2091.     realizes it is empty and puts it back down.'
  2092.     ]
  2093.     patrol =
  2094.     {
  2095.         if ( self.location = Me.location )
  2096.     {
  2097.             "\b";
  2098.             say( self.patrolMessage[rand( 5 )]);
  2099.     }
  2100.     }
  2101. ;
  2102.  
  2103. cardtable: fixeditem, surface
  2104.     noun = 'table'
  2105.     adjective = 'card'
  2106.     location = storage
  2107.     sdesc = "card table"
  2108. ;
  2109.  
  2110. emptyglass: container
  2111.     noun = 'glass'
  2112.     adjective = 'empty'
  2113.     sdesc = "empty glass"
  2114.     adesc = "an empty glass"
  2115.     location = cardtable
  2116.     doTake( actor ) =
  2117.     {
  2118.         if ( guard.isActive )
  2119.         "The guard won't let you take the glass. \"Get your own,\"
  2120.         he says. ";
  2121.     else pass doTake;
  2122.     }
  2123.     ioPutIn( actor, dobj ) =
  2124.     {
  2125.         if ( dobj = ln2 ) "The liquid nitrogen evaporates on contact. ";
  2126.     else "It won't fit in the glass. ";
  2127.     }
  2128. ;
  2129.  
  2130. tunnelSounds: function( parm )
  2131. {
  2132.     if ( Me.location.istunnel )
  2133.     {
  2134.         "\b";
  2135.     say( tunnelroom.randomsound[rand( 5 )]);
  2136.     }
  2137.     setfuse( tunnelSounds, rand( 5 ), nil );
  2138. }
  2139.  
  2140. class tunnelroom: room
  2141.     istunnel = true
  2142.     sdesc = "Steam Tunnel"
  2143.     randomsound = [
  2144.     // random sound 1
  2145.       'The rumbling sound suddenly becomes very loud, then, after
  2146.        a few moments, dies down to background levels again.'
  2147.     // random sound 2
  2148.       'A series of clanking noises, like marbles rolling through the
  2149.       steam pipes, starts in the distance, then comes
  2150.       closer and closer, until it seems to pass right overhead. It disappears
  2151.       into the distance.'
  2152.     // random sound 3
  2153.       'A very loud bang suddenly reverberates through the tunnel.'
  2154.     // random sound 4
  2155.       'One of the pipes starts to hiss wildly. After a few moments, it
  2156.       fades back into the background sounds.'
  2157.     // random sound 5
  2158.       'A loud buzzing sound, like an overloaded electrical circuit,
  2159.       emanates from somewhere nearby. After a few moments it is gone.'
  2160.     ]
  2161. ;
  2162.  
  2163. tunnelpipes: fixeditem
  2164.     sdesc = "pipes"
  2165.     noun = 'pipe' 'pipes'
  2166.     ldesc = "The pipes range from very small copper tubes only an inch around
  2167.      to huge asbestos-covered cylinders over two feet in diameter.  Many of
  2168.      the larger pipes are marked \"STEAM - 300 PSI.\" "
  2169.     locationOK = true
  2170.     location =
  2171.     {
  2172.         if ( Me.location.istunnel ) return( Me.location );
  2173.     else return( nil );
  2174.     }
  2175. ;
  2176.  
  2177. tunnel1: tunnelroom
  2178.     ldesc = "You are in a steam tunnel. It is very hot and dry in here.
  2179.      The place has a strange musty odor; the air is very still, but there
  2180.      are distant sounds of all sorts that vibrate through the pipes. The
  2181.      pipes all seem to be hissing quietly, and a low rumbling sound constantly
  2182.      reverberates through the tunnel. Occasionally a distant clang or thud
  2183.      or crack emanates from the pipes.
  2184.      \n\tThe steam tunnel runs east and west. A small passage leads south. "
  2185.     east = tunnel2
  2186.     west = tunnel3
  2187.     south = storage
  2188.     enterRoom( actor ) =
  2189.     {
  2190.         if ( not self.isseen ) setfuse( tunnelSounds, rand( 5 ), nil );
  2191.     pass enterRoom;
  2192.     }
  2193. ;
  2194.  
  2195. tunnel2: tunnelroom
  2196.     ldesc = "You are at the east end of the steam tunnel. "
  2197.     west = tunnel1
  2198. ;
  2199.  
  2200. tunnelStorage: room
  2201.     sdesc = "Storage Room"
  2202.     ldesc = "You are in a small storage room. The exit lies north. "
  2203.     north = tunnel13
  2204. ;
  2205.  
  2206. tunnel3: tunnelroom
  2207.     ldesc = "You are in an east-west section of the steam tunnels. "
  2208.     east = tunnel1
  2209.     west = tunnel4
  2210. ;
  2211.  
  2212. tunnel4: tunnelroom
  2213.     ldesc = "You are at a T-intersection of two sections of steam
  2214.      tunnel; tunnels go off to the north, south, and east. "
  2215.     east = tunnel3
  2216.     north = tunnel5
  2217.     south = tunnel6
  2218. ;
  2219.  
  2220. darktunnel: darkroom, tunnelroom
  2221.     controlon = nil
  2222.     islit =
  2223.     {
  2224.         if ( self.controlon ) return( true );
  2225.     else pass islit;
  2226.     }
  2227. ;
  2228.  
  2229. tunnel5: darktunnel
  2230.     ldesc = "You are at a corner in the steam tunnel: you can go
  2231.      west and south. "
  2232.     west = tunnel7
  2233.     south = tunnel4
  2234. ;
  2235.  
  2236. tunnel6: tunnelroom
  2237.     ldesc = "You are at a corner in the steam tunnel: you can go
  2238.      west and north. "
  2239.     west = tunnel8
  2240.     north = tunnel4
  2241. ;
  2242.  
  2243. tunnel7: darktunnel
  2244.     ldesc = "You are in an east-west section of the steam tunnel.
  2245.      A very small passage between some steam pipes leads north, but
  2246.      it would be a tight squeeze. "
  2247.     east = tunnel5
  2248.     west = tunnel9
  2249.     north =
  2250.     {
  2251.         return(crawltest( tunnel12,
  2252.          'You lay down on one of the pipes and start to snake
  2253.           through the passage. For a moment, you think you\'re
  2254.           stuck, but you manage to wriggle your way through. You
  2255.           emerge on the north side of the narrow crawl.' ));
  2256.     }
  2257. ;
  2258.  
  2259. tunnel8: tunnelroom
  2260.     controlon = true
  2261.     ldesc =
  2262.     {
  2263.         "You are in an east-west section of the steam tunnel. On the
  2264.          wall is a control unit. ";
  2265.     if ( not self.controlon )
  2266.     {
  2267.         "It is quite dark in this section of the tunnel; the only
  2268.          illumination is coming from the control unit's display";
  2269.          
  2270.         if (( flashlight.isIn( Me ) or flashlight.isIn( tunnel8 ))
  2271.          and flashlight.islit )
  2272.             " (and from the flashlight, of course)";
  2273.     
  2274.         ". ";
  2275.     }
  2276.     }
  2277.     east = tunnel6
  2278.     west = tunnel10
  2279. ;
  2280.  
  2281. controlunit: fixeditem
  2282.     sdesc = "control unit"
  2283.     noun = 'unit'
  2284.     adjective = 'control'
  2285.     location = tunnel8
  2286.     ldesc =
  2287.     {
  2288.         "The control unit is quite modern and high-tech looking, in
  2289.          stark contrast to the tunnels around it. It consists of a keypad
  2290.          which allows entry of arbitrary numbers, a large green button,
  2291.      and a display screen. The unit is labelled \"Station 2.\" ";
  2292.     controldisp.ldesc;
  2293.     }
  2294.     objref =
  2295.     {
  2296.         local l;
  2297.     
  2298.     l := self.value;
  2299.     
  2300.     if ( l = 322 ) return( tunnel8 );
  2301.     else if ( l = 612 ) return( mazeroom );
  2302.     else if ( l = 293 ) return( darktunnel );
  2303.     else return( nil );
  2304.     }
  2305.     value = 322
  2306. ;
  2307.  
  2308. controlpad: fixeditem
  2309.     sdesc = "keypad"
  2310.     noun = 'keypad' 'pad'
  2311.     adjective = 'key'
  2312.     location = tunnel8
  2313.     ldesc = "It's one of those cheesy membrane keypads, like on a microwave
  2314.      oven or the new Enterprise's control panels. It allows you to type numbers
  2315.      made up of digits from 0 to 9. "
  2316.     verIoTypeOn( actor ) = {}
  2317.     ioTypeOn( actor, dobj ) =
  2318.     {
  2319.         if ( dobj <> numObj )
  2320.         "The keypad only allows entry of numbers. ";
  2321.     else
  2322.     {
  2323.         "As you type the number sequence, the display screen is
  2324.         updated. ";
  2325.         controlunit.value := numObj.value;
  2326.         controldisp.ldesc;
  2327.     }
  2328.     }
  2329. ;
  2330.  
  2331. controlbutton: buttonitem
  2332.     sdesc = "button"
  2333.     adjective = 'green'
  2334.     location = tunnel8
  2335.     doPush( actor ) =
  2336.     {
  2337.         local r;
  2338.     
  2339.     r := controlunit.objref;
  2340.     if ( r )
  2341.     {
  2342.         "The display is updated as you press the button. ";
  2343.         r.controlon := not r.controlon;
  2344.         controldisp.ldesc;
  2345.         if ( r = tunnel8 )
  2346.         {
  2347.             "The lights in the tunnel ";
  2348.             if ( r.controlon )
  2349.             "come on. ";
  2350.         else
  2351.         {
  2352.             "go out, leaving only the display screen's light ";
  2353.             if (( flashlight.isIn( Me ) or flashlight.isIn( tunnel8 ))
  2354.              and flashlight.islit )
  2355.                 "(and the flashlight, of course) ";
  2356.             "for illumination. ";
  2357.         }
  2358.         }
  2359.     }
  2360.     else "The unit beeps; nothing else appears to happen. ";
  2361.     }
  2362. ;
  2363.  
  2364. controldisp: fixeditem
  2365.     sdesc = "display screen"
  2366.     noun = 'screen'
  2367.     adjective = 'display'
  2368.     location = tunnel8
  2369.     ldesc =
  2370.     {
  2371.         local l, r;
  2372.     
  2373.     l := controlunit.value;
  2374.     r := controlunit.objref;
  2375.         "The screen is currently displaying: \""; say( l ); ": ";    
  2376.     if ( r )
  2377.     {
  2378.         if ( r.controlon ) "ON"; else "OFF";
  2379.     }
  2380.     else "???";
  2381.     
  2382.     "\". ";
  2383.     }
  2384. ;
  2385.  
  2386. tunnel9: darktunnel
  2387.     ldesc = "You are at a corner in the steam tunnel.  You can go east
  2388.      or south. "
  2389.     east = tunnel7
  2390.     south = tunnel11
  2391. ;
  2392.  
  2393. tunnel10: tunnelroom
  2394.     ldesc = "You are at a corner in the steam tunnel. You can go east
  2395.      or north. "
  2396.     east = tunnel8
  2397.     north = tunnel11
  2398. ;
  2399.  
  2400. tunnel11: tunnelroom
  2401.     ldesc = "You are in a north-south section of the steam tunnels. Set
  2402.      into one wall is a large chute. "
  2403.     north = tunnel9
  2404.     south = tunnel10
  2405. ;
  2406.  
  2407. chute: fixeditem, container
  2408.     sdesc = "chute"
  2409.     noun = 'chute'
  2410.     location = tunnel11
  2411.     ldesc = "The chute is large enough for anything you're carrying,
  2412.      but not nearly big enough for you. You can't tell where it goes,
  2413.      except down. "
  2414.     ioPutIn( actor, dobj ) =
  2415.     {
  2416.         "You put "; dobj.thedesc; " into the chute, and it slides away
  2417.     into the darkness. After a few moments, you hear a soft thud. ";
  2418.     dobj.moveInto( chuteroom );
  2419.     }
  2420. ;
  2421.  
  2422. crawltest: function( rm, msg )
  2423. {
  2424.     local i;
  2425.     
  2426.     i := 1;
  2427.     while ( i <= length( Me.contents ))
  2428.     {
  2429.         if ( not Me.contents[i].iscrawlable )
  2430.     {
  2431.         "You'll never get through carrying ";
  2432.         Me.contents[i].thedesc; ". ";
  2433.         return( nil );
  2434.     }
  2435.         i := i + 1;
  2436.     }
  2437.     say( msg ); "\b";
  2438.     return( rm );
  2439. }
  2440.  
  2441. tunnel12: tunnelroom
  2442.     ldesc =
  2443.     {
  2444.         if ( self.isseen )
  2445.             "You are in an east-west section of the steam tunnels. A narrow
  2446.             passage between some steam pipes might allow you to go south. ";
  2447.     else
  2448.         "You are in another steam tunnel, but this one is substantially
  2449.         different from the tunnels you have been in so far. This tunnel
  2450.         is much wider, less cluttered; it looks like it was built more
  2451.         recently than the south tunnels. The tunnel itself runs east
  2452.         and west, and passing back to the south is evidently possible,
  2453.         given your presence here. ";
  2454.     }
  2455.     east = tunnel13
  2456.     west = pitTop
  2457.     south =
  2458.     {
  2459.         return(crawltest( tunnel7, 'Going through the crawl
  2460.      southbound is just as difficult as it was coming north,
  2461.      you observe.' ));
  2462.     }
  2463. ;
  2464.  
  2465. tunnel13: tunnelroom
  2466.     ldesc = "You are at the east end of a steam tunnel. A passage leads
  2467.      north, and another one leads south. "
  2468.     west = tunnel12
  2469.     north = maze0
  2470.     south = tunnelStorage
  2471. ;
  2472.  
  2473. maze0: room
  2474.     sdesc = "Outside Maze"
  2475.     ldesc =
  2476.     {
  2477.         "You are in a small room, with exits north and south. The
  2478.          passage to the north has a small sign reading \"Behavior Lab Maze\";
  2479.          the room is filled with strange equipment, which you surmise is
  2480.          connected in some way to the maze. ";
  2481.      
  2482.     if ( mazeroom.controlon )
  2483.         "The equipment is buzzing loudly. Standing
  2484.          near it makes you feel vaguely dizzy. ";
  2485.     
  2486.     if ( not self.isseen )
  2487.     {
  2488.         "\n\tYou sigh in resignation as you realize that you have reached
  2489.         the obligatory Adventure Game Maze, and ";
  2490.         if ( mazeview.isseen )
  2491.             "wish that this were a graphical adventure, so your trip to
  2492.         the maze viewing room had resulted in a map you could refer
  2493.         to now. Fortunately, you do recall noting that the passages
  2494.         in the maze all lead east-west or north-south. ";
  2495.             else
  2496.             "wonder what this maze's unique twist will be. Surely, it
  2497.         won't just be a boring old labyrinth... ";
  2498.     }
  2499.     }
  2500.     south = tunnel13
  2501.     north = maze1
  2502. ;
  2503.  
  2504. mazeequip: decoration
  2505.     noun = 'equipment' 'coil' 'coils' 'pipe' 'pipes' 'wire' 'wires'
  2506.     adjective = 'electric' 'electrical'
  2507.     sdesc = "equipment"
  2508.     location = maze0
  2509.     ldesc =
  2510.     {
  2511.         "The equipment resembles some of the particle accelerators that
  2512.     you have seen. It has several huge electric coils, all arranged
  2513.     around a series of foot-diameter pipes. A tangled web of enormous
  2514.     wires connects various parts of the equipment together and other
  2515.     wires feed it power. ";
  2516.     
  2517.         if ( mazeroom.controlon )
  2518.         "The equipment is buzzing loudly. Standing near it makes
  2519.         you feel vaguely dizzy. ";
  2520.     }
  2521. ;
  2522.  
  2523. mazeroom: room
  2524.     controlon = true
  2525.     sdesc = "Lost in the Maze"
  2526.     lookAround( verbosity ) =
  2527.     {
  2528.         self.statusLine;
  2529.     self.nrmLkAround( self.controlon ? true : verbosity );
  2530.     }
  2531.     ldesc =
  2532.     {
  2533.         if ( self.controlon )
  2534.         "You can't quite seem to get your bearings. There are some
  2535.         passages leading away, but you can't quite tell how many or
  2536.         in which direction they leads. ";
  2537.     else
  2538.     {
  2539.         local cnt, tot, i;
  2540.         
  2541.         tot := 0;
  2542.         i := 1;
  2543.         while ( i <= 4 )
  2544.         {
  2545.             if ( self.dirlist[i] ) tot := tot + 1;
  2546.             i := i + 1;
  2547.         }
  2548.  
  2549.         "You are in a room in the maze; they all look alike.
  2550.         You can go ";
  2551.         
  2552.         i := 1;
  2553.         cnt := 0;
  2554.         while ( i <= 4 )
  2555.         {
  2556.             if ( self.dirlist[i] )
  2557.         {
  2558.             if ( cnt > 0 )
  2559.             {
  2560.                 if ( tot = 2 ) " and ";
  2561.             else if ( cnt+1 = tot ) ", and ";
  2562.             else ", ";
  2563.             }
  2564.             cnt := cnt + 1;
  2565.             
  2566.             say( ['north' 'south' 'east' 'west'][i] );
  2567.         }
  2568.             i := i + 1;
  2569.         }
  2570.         ". ";
  2571.     }
  2572.     }
  2573.     mazetravel( rm ) =
  2574.     {
  2575.         if ( self.controlon )
  2576.     {
  2577.         local r;
  2578.         
  2579.         "You can't figure out which direction is which; the more you
  2580.         stumble about, the more the room seems to spin around. After a
  2581.         few steps, you're not sure if you've actually gone anywhere,
  2582.         since all these rooms look alike...\b";
  2583.         
  2584.         /*
  2585.          *   We know we can only go one of four directions, but generate
  2586.          *   a random number up to 6; if we generate 5 or 6, we won't go
  2587.          *   anywhere, but we won't let on that this is the case.
  2588.          */
  2589.         r := rand( 6 );
  2590.         
  2591.         /*
  2592.          *   Note that we want to confuse the player in active-maze mode
  2593.          *   as much as possible, so we don't want any clues as to whether
  2594.          *   there was any travel in this direction or not.  So, return
  2595.          *   "self" rather than "nil," since we won't get any message if
  2596.          *   we return "nil," but we'll get the current room's message if
  2597.          *   we return "self;" since all the messages are the same, this
  2598.          *   won't provide any information.
  2599.          */
  2600.         if ( r < 5 )
  2601.         {
  2602.             r := self.dirlist[ r ];
  2603.         if ( r ) return( r );
  2604.         else return( self );
  2605.         }
  2606.         else return( self );
  2607.     }
  2608.     else
  2609.     {
  2610.         if ( rm )
  2611.             return( rm );
  2612.         else
  2613.         {
  2614.             "You can't go that way. ";
  2615.             return( nil );
  2616.         }
  2617.     }
  2618.     }
  2619.     north = ( self.mazetravel( self.dirlist[1] ))
  2620.     south = ( self.mazetravel( self.dirlist[2] ))
  2621.     east = ( self.mazetravel( self.dirlist[3] ))
  2622.     west = ( self.mazetravel( self.dirlist[4] ))
  2623.     up = ( self.mazetravel( 0 ))
  2624.     down = ( self.mazetravel( 0 ))
  2625.     in = ( self.mazetravel( 0 ))
  2626.     out = ( self.mazetravel( 0 ))
  2627.     ne = ( self.mazetravel( 0 ))
  2628.     nw = ( self.mazetravel( 0 ))
  2629.     se = ( self.mazetravel( 0 ))
  2630.     sw = ( self.mazetravel( 0 ))
  2631. ;
  2632.  
  2633. maze1: mazeroom
  2634.     dirlist = [ 0 maze0 maze2 0 ]
  2635. ;
  2636.  
  2637. maze2: mazeroom
  2638.     dirlist = [ maze9 0 maze3 maze1 ]
  2639. ;
  2640.  
  2641. maze3: mazeroom
  2642.     dirlist = [ maze8 0 maze4 maze2 ]
  2643. ;
  2644.  
  2645. maze4: mazeroom
  2646.     dirlist = [ 0 0 maze5 maze3 ]
  2647. ;
  2648.  
  2649. maze5: mazeroom
  2650.     dirlist = [ maze6 0 0 maze4 ]
  2651. ;
  2652.  
  2653. maze6: mazeroom
  2654.     dirlist = [ 0 maze5 0 maze7 ]
  2655. ;
  2656.  
  2657. maze7: mazeroom
  2658.     dirlist = [ maze30 0 maze9 maze8 ]
  2659. ;
  2660.  
  2661. maze8: mazeroom
  2662.     dirlist = [ maze29 maze3 maze7 0 ]
  2663. ;
  2664.  
  2665. maze9: mazeroom
  2666.     dirlist = [ 0 maze2 0 maze10 ]
  2667. ;
  2668.  
  2669. maze10: mazeroom
  2670.     dirlist = [ 0 0 maze9 maze11 ]
  2671. ;
  2672.  
  2673. maze11: mazeroom
  2674.     dirlist = [ 0 maze35 maze10 maze12 ]
  2675. ;
  2676.  
  2677. maze12: mazeroom
  2678.     dirlist = [ 0 0 maze11 0 ]
  2679. ;
  2680.  
  2681. maze13: mazeroom
  2682.     dirlist = [ maze24 maze18 0 0 ]
  2683. ;
  2684.  
  2685. maze14: mazeroom
  2686.     dirlist = [ 0 maze17 0 maze15 ]
  2687. ;
  2688.  
  2689. maze15: mazeroom
  2690.     dirlist = [ 0 maze16 maze14 0 ]
  2691. ;
  2692.  
  2693. maze16: mazeroom
  2694.     dirlist = [ maze15 maze23 maze17 0 ]
  2695. ;
  2696.  
  2697. maze17: mazeroom
  2698.     dirlist = [ maze14 maze22 maze18 maze16 ]
  2699. ;
  2700.  
  2701. maze18: mazeroom
  2702.     dirlist = [ maze13 maze21 0 maze17 ]
  2703. ;
  2704.  
  2705. maze19: mazeroom
  2706.     dirlist = [ 0 maze20 maze35 0 ]
  2707. ;
  2708.  
  2709. maze20: mazeroom
  2710.     dirlist = [ maze19 0 0 maze21 ]
  2711. ;
  2712.  
  2713. maze21: mazeroom
  2714.     dirlist = [ maze18 0 maze20 0 ]
  2715. ;
  2716.  
  2717. maze22: mazeroom
  2718.     dirlist = [ maze17 0 0 0 ]
  2719. ;
  2720.  
  2721. maze23: mazeroom
  2722.     dirlist = [ maze16 0 0 0 ]
  2723. ;
  2724.  
  2725. maze24: mazeroom
  2726.     dirlist = [ 0 maze13 maze25 0 ]
  2727. ;
  2728.  
  2729. maze25: mazeroom
  2730.     dirlist = [ maze33 0 maze26 maze24 ]
  2731. ;
  2732.  
  2733. maze26: mazeroom
  2734.     dirlist = [ maze32 0 0 maze25 ]
  2735. ;
  2736.  
  2737. maze27: mazeroom
  2738.     dirlist = [ maze31 0 0 0 ]
  2739. ;
  2740.  
  2741. maze28: mazeroom
  2742.     dirlist = [ 0 0 maze29 0 ]
  2743. ;
  2744.  
  2745. maze29: mazeroom
  2746.     dirlist = [ 0 maze8 maze30 maze28 ]
  2747. ;
  2748.  
  2749. maze30: mazeroom
  2750.     dirlist = [ 0 maze7 0 maze29 ]
  2751. ;
  2752.  
  2753. maze31: mazeroom
  2754.     dirlist = [ 0 maze27 0 maze32 ]
  2755. ;
  2756.  
  2757. maze32: mazeroom
  2758.     dirlist = [ 0 maze26 maze31 0 ]
  2759. ;
  2760.  
  2761. maze33: mazeroom
  2762.     dirlist = [ 0 maze25 0 maze34 ]
  2763. ;
  2764.  
  2765. maze34: mazeroom
  2766.     dirlist = [ 0 0 maze33 mazeStart ]
  2767. ;
  2768.  
  2769. maze35: mazeroom
  2770.     dirlist = [ maze11 0 0 maze19 ]
  2771. ;
  2772.  
  2773. mazeStart: room
  2774.     sdesc = "Start of Maze"
  2775.     ldesc = "You are at the start of the maze. A passage into the
  2776.      maze is to the east, and a heavy one-way door marked \"Exit\" is to the
  2777.      south. "
  2778.     east = maze34
  2779.     south = behaviorLab
  2780. ;
  2781.  
  2782. mazedoor: fixeditem
  2783.     sdesc = "door"
  2784.     noun = 'door'
  2785.     adjective = 'exit' 'one-way' 'heavy'
  2786.     verDoOpen( actor ) = { "No need; just walk on through. "; }
  2787.     location = mazeStart
  2788. ;
  2789.  
  2790. chuteroom: room
  2791.     sdesc = "Chute Room"
  2792.     ldesc = "You are in a small room with exits to the northwest
  2793.      and south. The bottom of a large chute opens into the room. "
  2794.     nw = pitBottom
  2795.     south = shiproom
  2796. ;
  2797.  
  2798. chute2: fixeditem, container
  2799.     sdesc = "chute"
  2800.     noun = 'chute'
  2801.     location = chuteroom
  2802.     ioPutIn( actor, dobj ) =
  2803.     {
  2804.         "This is the bottom of the chute; you can't put objects
  2805.     into it. ";
  2806.     }
  2807. ;
  2808.  
  2809. pitTop: tunnelroom
  2810.     sdesc = "Top of Pit"
  2811.     ldesc =
  2812.     {
  2813.         "You are in a large open area in the steam tunnels. In
  2814.          the center of the room is a large pit, around which is a protective
  2815.          railing. A steam tunnel is to the east. ";
  2816.     if ( rope.tieItem = railing )
  2817.         "A rope is tied to the railing, and extends down into the pit. ";
  2818.     }
  2819.     east = tunnel12
  2820.     down =
  2821.     {
  2822.         if ( rope.tieItem = railing )
  2823.     {
  2824.         "You climb down the rope...\b";
  2825.         return( pitBottom );
  2826.     }
  2827.     else
  2828.     {
  2829.         "You'd probably break your neck if you tried to jump
  2830.         into the pit. ";
  2831.             return( nil );
  2832.     }
  2833.     }
  2834. ;
  2835.  
  2836. tieVerb: deepverb
  2837.     sdesc = "tie"
  2838.     verb = 'tie'
  2839.     prepDefault = toPrep
  2840.     ioAction( toPrep ) = 'TieTo'
  2841. ;
  2842.  
  2843. railing: fixeditem
  2844.     sdesc = "rail"
  2845.     noun = 'rail' 'railing'
  2846.     location = pitTop
  2847.     verIoTieTo( actor ) = {}
  2848.     ioTieTo( actor, dobj ) =
  2849.     {
  2850.         "You tie one end of the rope to the railing, and lower the other
  2851.     end into the pit. It appears to extend to the bottom of the pit. ";
  2852.     rope.tieItem := self;
  2853.     rope.moveInto( pitTop );
  2854.     rope.isfixed := true;
  2855.     }
  2856. ;
  2857.  
  2858. climbupVerb: deepverb
  2859.     verb = 'climb up'
  2860.     sdesc = "climb up"
  2861.     doAction = 'Climbup'
  2862. ;
  2863.  
  2864. climbdownVerb: deepverb
  2865.     verb = 'climb down'
  2866.     sdesc = "climb down"
  2867.     doAction = 'Climbdown'
  2868. ;
  2869.  
  2870. rope: item
  2871.     sdesc = "rope"
  2872.     isListed = ( not self.isfixed )
  2873.     noun = 'rope'
  2874.     location = tunnelStorage
  2875.     ldesc =
  2876.     {
  2877.         if ( self.tieItem )
  2878.     {
  2879.         "It's tied to "; self.tieItem.thedesc; ". ";
  2880.     }
  2881.     else pass ldesc;
  2882.     }
  2883.     verDoTieTo( actor, io ) =
  2884.     {
  2885.         if ( self.tieItem )
  2886.     {
  2887.         "It's already tied to "; self.tieItem.thedesc; "! ";
  2888.     }
  2889.     }
  2890.     doTake( actor ) =
  2891.     {
  2892.         if ( self.tieItem )
  2893.     {
  2894.         "(You untie it first, of course.) ";
  2895.         self.tieItem := nil;
  2896.         self.isfixed := nil;
  2897.     }
  2898.     pass doTake;
  2899.     }
  2900.     verDoClimb( actor ) =
  2901.     {
  2902.         if ( self.tieItem = nil )
  2903.         "Climbing down the rope in its present configuration would
  2904.         get you nowhere. ";
  2905.     }
  2906.     doClimb( actor ) =
  2907.     {
  2908.         "You climb down the rope...\b";
  2909.         Me.travelTo( pitBottom );
  2910.     }
  2911.     verDoClimbdown( actor ) = {}
  2912.     doClimbdown( actor ) = { self.doClimb( actor ); }
  2913. ;
  2914.  
  2915. pitBottom: room
  2916.     sdesc = "Huge Cavern"
  2917.     ldesc = "You are in a huge and obviously artificial cavern. The cave
  2918.      has apparently been dug out over a long period of time; some parts
  2919.      look very old, and other areas look comparatively recent. A small bronze
  2920.      plaque affixed to one of the older walls reads, \"Great Undergraduate
  2921.      Excavation - 1982.\"
  2922.      From high above, a small opening in
  2923.      the ceiling casts a dim glow over the vast chamber. A rope extends
  2924.      from the opening above. Passages of various ages lead north, south,
  2925.      east, west, southeast, and southwest. "
  2926.     up =
  2927.     {
  2928.         "It's a long climb, but you somehow manage it.\b";
  2929.         return( pitTop );
  2930.     }
  2931.     se = chuteroom
  2932.     east = biohall1
  2933.     south = bank
  2934.     north = cave
  2935.     sw = insOffice
  2936.     west = machineshop
  2937. ;
  2938.  
  2939. pitplaque: fixeditem, readable
  2940.     noun = 'plaque'
  2941.     sdesc = "bronze plaque"
  2942.     adjective = 'bronze' 'small'
  2943.     location = pitBottom
  2944.     ldesc = "Great Undergraduate Excavation\n\t\t\t1982"
  2945. ;
  2946.  
  2947. insOffice: room
  2948.     sdesc = "Insurance Office"
  2949.     ldesc =
  2950.     {
  2951.         "You are in an insurance office. Like most insurance offices,
  2952.     the area is rather non-descript. The exit is northeast. ";
  2953.     if ( not self.isseen )
  2954.     {
  2955.         "\n\tAs you walk into the office, a large metallic robot, very
  2956.         much like the traditional sci-fi film robot, but wearing a dark
  2957.         polyester business suit, zips up to you. \"Hi, I'm Lloyd the
  2958.         Friendly Insurance Robot,\" he says in a mechanical British
  2959.         accent. \"You look like you could use some insurance! Here, let
  2960.         me prepare a policy for you.\"
  2961.         \n\tLloyd scurries around the room, gathering papers and
  2962.         studying charts, occasionally zipping up next to you and
  2963.         measuring your height and other dimensions, making all kinds
  2964.         of notes, and generally scampering about. After a few minutes,
  2965.         he comes up to you, showing you a piece of paper.
  2966.         \n\t\"I have the perfect policy for you. Just one dollar will
  2967.         buy you a hundred thousand worth of insurance!\" He watches
  2968.         you anxiously. ";
  2969.         
  2970.         notify( lloyd, #offerins, 0 );
  2971.     }
  2972.     }
  2973.     ne = pitBottom
  2974.     out = pitBottom
  2975. ;
  2976.  
  2977. /*
  2978.  *   Lloyd the Friendly Insurance Robot is a full-featured actor. He will
  2979.  *   initially just wait in his office until paid for a policy, but will
  2980.  *   thereafter follow the player around relentlessly.  Lloyd doesn't
  2981.  *   interact much, though; he just hangs around and does wacky things.
  2982.  */
  2983. lloyd: Actor
  2984.     noun = 'lloyd' 'him'
  2985.     sdesc = "Lloyd"
  2986.     adesc = "Lloyd"
  2987.     thedesc = "Lloyd"
  2988.     ldesc = "Lloyd the Friendly Insurance Robot is a strange combination
  2989.      of the traditional metallic robot and an insurance salesman; over his
  2990.      bulky metal frame is a polyester suit. "
  2991.     actorAction( v, d, p, i ) =
  2992.     {
  2993.         if ( v = helloVerb )
  2994.         "\"Hello,\" Lloyd responds cheerfully. ";
  2995.     else if ( v = followVerb and d = Me )
  2996.     {
  2997.         if ( self.offering )
  2998.             "\"Sorry, but I must stay here until I've made a sale.\" ";
  2999.         else
  3000.             "\"I will follow you,\" Lloyd says. \"That will allow me
  3001.         to pay any claim you make immediately should the need arise.
  3002.         It's just one of the ways we keep our overhead so low.\" ";
  3003.     }
  3004.     else
  3005.         "\"I'm sorry, that's not in your policy.\" ";
  3006.     exit;
  3007.     }
  3008.     verDoAskAbout( actor, io ) = {}
  3009.     doAskAbout( actor, io ) =
  3010.     {
  3011.         if ( io = policy )
  3012.         "\"Your policy perfectly fits your needs, according to my
  3013.         calculations,\" Lloyd says. \"I'm afraid it's much too
  3014.         complicated to go into in any detail right now, but you have
  3015.         my assurances that you won't be disappointed.\" ";
  3016.     else
  3017.         "\"I'm afraid I don't know much about that,\" Lloyd says
  3018.         apologetically. ";
  3019.     }
  3020.     actorDesc =
  3021.     {
  3022.         if ( self.offering )
  3023.         "Lloyd is here, offering you an insurance policy for only
  3024.         one dollar. ";
  3025.     else
  3026.         "Lloyd the Friendly Insurance Robot is here. ";
  3027.     }
  3028.     offering = true
  3029.     offermsg =
  3030.     [
  3031.         'Lloyd waits patiently for you to make up your mind about the
  3032.      insurance policy.'
  3033.     'Lloyd watches you expectantly, hoping you will buy the insurance
  3034.      policy.'
  3035.     'Lloyd shows you the insurance policy again. "Only a dollar," he
  3036.      says.'
  3037.     'Lloyd looks at you intently. "What can I do to make you buy this
  3038.      insurance policy right now?" he asks rhetorically.'
  3039.     'Lloyd reviews the policy to make sure it looks just right, and
  3040.      offers it to you again.'
  3041.     ]
  3042.     offerins =
  3043.     {
  3044.         if ( self.location = Me.location )
  3045.     {
  3046.         "\b";
  3047.         say(self.offermsg[rand( 5 )]);
  3048.     }
  3049.     }
  3050.     followmsg =
  3051.     [
  3052.         'Lloyd watches attentively to make sure you don\'t hurt yourself.'
  3053.     'Lloyd hums one of his favorite insurance songs.'
  3054.     'Lloyd gets out some actuarial tables and does some computations.'
  3055.     'Lloyd looks through his papers.'
  3056.     'Lloyd checks the area to make sure it\'s safe.'
  3057.     ]
  3058.     follow =
  3059.     {
  3060.         if ( Me.location = machinestorage ) return;
  3061.     
  3062.     "\b";
  3063.         if ( self.location <> Me.location )
  3064.     {
  3065.         if ( Me.location = railcar )
  3066.             "Lloyd hops into the railcar, showing remarkable agility
  3067.         for such a large mechanical device. ";
  3068.         else if ( self.location = railcar )
  3069.             "Lloyd hops out of the railcar. ";
  3070.         else if ( Me.location = pitTop and self.location = pitBottom )
  3071.             "Amazingly, Lloyd scrambles up the rope and joins you. ";
  3072.         else if ( Me.location = pitBottom and self.location = pitTop )
  3073.             "Lloyd descends smoothly down the rope and joins you. ";
  3074.         else if (( Me.location = tunnel7 and self.location = tunnel12 )
  3075.          or ( Me.location = tunnel12 and self.location = tunnel7 ))
  3076.             "Somehow, Lloyd manages to squeeze through the crawl. ";
  3077.         else if ( Me.location = quad )
  3078.             "Lloyd follows you. When he sees the apparent radioactive
  3079.         waste spill, he is quite alarmed. After a moment, though,
  3080.         he deduces that the spill is a staged part of the Ditch Day
  3081.         festivities, and he calms down. ";
  3082.         else if ( Me.location = storage )
  3083.             "Lloyd enters the storage room. Upon seeing the guard, he
  3084.             rolls over and starts giving his insurance pitch. After a
  3085.         moment, he notices the guard is unconscious. \"It's just as
  3086.         well,\" Lloyd confides; \"security work is awfully risky, and
  3087.         his rates would have been quite high.\" ";
  3088.         else
  3089.             "Lloyd follows you. ";
  3090.         
  3091.         self.moveInto( Me.location );
  3092.     }
  3093.     else
  3094.     {
  3095.         say(self.followmsg[rand( 5 )]);
  3096.     }
  3097.     }
  3098.     verIoGiveTo( actor ) = {}
  3099.     ioGiveTo( actor, dobj ) =
  3100.     {
  3101.         if ( dobj = dollar )
  3102.         self.doPay( actor );
  3103.     else if ( dobj = darbcard )
  3104.         "Lloyd looks at you apologetically. \"So sorry, I must insist
  3105.         on cash,\" he says. ";
  3106.     else
  3107.         "Lloyd doesn't appear interested. ";
  3108.     }
  3109.     verDoPay( actor ) = {}
  3110.     doPay( actor ) =
  3111.     {
  3112.         if ( not self.offering )
  3113.     {
  3114.         "Lloyd looks at you, confused. \"I've already sold you all
  3115.         the insurance you need!\" ";
  3116.     }
  3117.         else if ( dollar.isIn( actor ))
  3118.     {
  3119.         "Lloyd graciously accepts the payment, and hands you a copy
  3120.         of your policy. \"You might wonder how we keep costs so low,\"
  3121.         Lloyd says. \"It's simple: we're highly automated, which keeps
  3122.         labor costs low; I run the whole company, which keeps the
  3123.         bureaucratic overhead low; and, most importantly, I follow you
  3124.         everywhere you go for the duration of the policy, ensuring that
  3125.         you're paid on the spot should anything happen, which means we
  3126.         don't have to waste money investigating claims!\" ";
  3127.         
  3128.         unnotify( self, #offerins );
  3129.         notify( self, #follow, 0 );
  3130.         dollar.moveInto( nil );
  3131.         policy.moveInto( Me );
  3132.         self.offering := nil;
  3133.     }
  3134.     else
  3135.     {
  3136.         "You don't have any money with which to pay Lloyd. ";
  3137.     }
  3138.     }
  3139.     location = insOffice
  3140. ;
  3141.  
  3142. policy: readable
  3143.     sdesc = "insurance policy"
  3144.     adesc = "an insurance policy"
  3145.     iscrawlable = true
  3146.     noun = 'policy'
  3147.     adjective = 'insurance'
  3148.     location = lloyd
  3149.     ldesc =
  3150.     {
  3151.         "The insurance policy lists the payment schedule for hundreds
  3152.     of types of injuries; the list is far too lengthy to go into in any
  3153.     detail here, but rest assured, ";
  3154.     if ( lloyd.offering )
  3155.         "it looks like an excellent deal. ";
  3156.     else
  3157.         "you're highly satisified with what you
  3158.         got for your dollar. You feel extremely well protected. ";
  3159.     }
  3160. ;
  3161.  
  3162. machineshop: room
  3163.     sdesc = "Machine Shop"
  3164.     ldesc = "You are in the machine shop. It appears that this huge
  3165.      chamber was once used to build and maintain the equipment that
  3166.      was used to create the Great Undergraduate Excavation.  Though
  3167.      most of the equipment is gone now, one very large and strange
  3168.      machine dominates the center of the room.
  3169.      The exit is east, and a small passage leads north. "
  3170.     east = pitBottom
  3171.     out = pitBottom
  3172.     north = machinestorage
  3173. ;
  3174.  
  3175. machine: fixeditem
  3176.     sdesc = "machine"
  3177.     noun = 'machine'
  3178.     location = machineshop
  3179.     ldesc = "The machine is unlike anything you've seen before; it's not
  3180.      at all clear what its purpose is. The only feature that looks like it
  3181.      might do anything useful is a large red button labelled \"DANGER!\" "
  3182. ;
  3183.  
  3184. machinebutton: buttonitem
  3185.     location = machineshop
  3186.     sdesc = "red button"
  3187.     adjective = 'red'
  3188.     doPush( actor ) =
  3189.     {
  3190.         "As you push the button, the machine starts making horrible noises
  3191.     and flinging huge metal rods in all directions. Enormous clouds of
  3192.     smoke rise from the machine as it flails about. After a few minutes
  3193.     of this behavior, you think to step back from the machine.  You're
  3194.     not fast enough, though; before you can escape it, a stray metal
  3195.     bar flings itself against your thumb, creating a sensation not unlike
  3196.     intense pain. ";
  3197.     
  3198.         if ( lloyd.location = self.location )
  3199.     {
  3200.         "\n\t";
  3201.             if ( self.isscored )
  3202.             "Lloyd looks at you apologetically. \"I don't want to sound
  3203.         patronizing, but you knew it would do that. I'm afraid I can't
  3204.         accept a claim for that injury, as it was effectively
  3205.         self-inflicted.\" He looks at you sadly. \"I do sympathize,
  3206.         though. That must be quite painful,\" he understates. ";
  3207.         else
  3208.         {
  3209.             self.isscored := true;
  3210.         "Lloyd rolls over and looks at your thumb. \"That looks
  3211.         awful,\" he says as you jump about, holding your thumb.
  3212.         Lloyd produces a thick pile of paper and starts leafing
  3213.         through it. \"Temporary loss of use of one thumb... ah,
  3214.         yes, here it is. That injury pays five dollars.\" Lloyd puts
  3215.         away his papers and produces a crisp new five dollar bill,
  3216.         which you accept (with your other hand). ";
  3217.         money.moveInto( Me );
  3218.         }
  3219.     }
  3220.     }
  3221. ;
  3222.  
  3223. machinestorage: darkroom
  3224.     sdesc = "Storage Closet"
  3225.     ldesc = "You are in a small storage closet off the machine shop.
  3226.      The exit is south. "
  3227.     south = machineshop
  3228.     out = machineshop
  3229. ;
  3230.  
  3231. happygear: treasure
  3232.     location = machinestorage
  3233.     noun = 'gear'
  3234.     adjective = 'mr.' 'mr' 'happy' 'mister'
  3235.     sdesc = "Mr.\ Happy Gear"
  3236.     thedesc = "Mr.\ Happy Gear"
  3237.     adesc = "Mr.\ Happy Gear"
  3238.     ldesc = "It's an ordinary gear, about an inch in diameter; the only
  3239.      notable feature is that it has holes cut in such a manner that it
  3240.      looks like a happy face. "
  3241. ;
  3242.  
  3243. bank: room
  3244.     sdesc = "Bank"
  3245.     ldesc = "You're in what was once the Great Undergraduate Excavation's
  3246.      bank. It doesn't appear to get much use any more. The exit is north,
  3247.      and a small passage leads south. "
  3248.     north = pitBottom
  3249.     south = bankvault
  3250.     out = pitBottom
  3251. ;
  3252.  
  3253. bankvault: room
  3254.     sdesc = "Vault Room"
  3255.     ldesc = "The feature dominating this room is the bank's safe.
  3256.      The only exit is north. "
  3257.     north = bank
  3258.     out = bank
  3259. ;
  3260.  
  3261. banksafe: fixeditem, openable
  3262.     sdesc = "safe"
  3263.     noun = 'safe' 'door' 'vault'
  3264.     location = bankvault
  3265.     isopen = nil
  3266.     ldesc =
  3267.     {
  3268.         if ( self.isblasted )
  3269.     {
  3270.         "The safe looks as though it has suffered some sort of
  3271.         intense trauma lately; the door is just barely hanging on
  3272.         its hinges, leaving the contents of the safe quite exposed. ";
  3273.         pass ldesc;
  3274.     }
  3275.     else
  3276.     {
  3277.         "The safe is huge, like the type you might find in a bank.
  3278.         The only notable features are a huge metal door (quite closed),
  3279.         and a large slot labelled \"Night Deposit Slot.\" ";
  3280.     }
  3281.     }
  3282.     doOpen( actor ) =
  3283.     {
  3284.         if ( self.isblasted ) pass doOpen;
  3285.     else
  3286.         "You can't open such a secure safe without resorting
  3287.          to some sort of drastic action. ";
  3288.     }
  3289. ;
  3290.  
  3291. darbcard: treasure
  3292.     sdesc = "DarbCard"
  3293.     noun = 'darbcard' 'card'
  3294.     adjective = 'darb'
  3295.     location = banksafe
  3296. ;
  3297.  
  3298. bankslot: fixeditem, container
  3299.     sdesc = "night deposit slot"
  3300.     noun = 'slot'
  3301.     adjective = 'night' 'deposit'
  3302.     location = bankvault
  3303.     ldesc = "The slot is very large, big enough to put a large sack of
  3304.      money into. Unfortunately, you won't have much luck extracting anything
  3305.      from the slot, since it has been carefully constructed to allow items
  3306.      to enter, but not leave. "
  3307.     ioPutIn( actor, dobj ) =
  3308.     {
  3309.         "\^<< dobj.thedesc >> disappears into the deposit slot. ";
  3310.     dobj.moveInto( banksafe );
  3311.     }
  3312. ;
  3313.  
  3314. cave: room
  3315.     sdesc = "Tunnel"
  3316.     ldesc = "You're in a north-south tunnel. The tunnel slopes steeply
  3317.      downward to the north. "
  3318.     north = railway1
  3319.     down = railway1
  3320.     south = pitBottom
  3321.     up = pitBottom
  3322. ;
  3323.  
  3324. railway1: room
  3325.     sdesc = "Subway Station"
  3326.     ldesc = "You're in a very large musty chamber deep underground. In the
  3327.      center of the room is a small rail car. Strangely, the car is sitting on
  3328.      the floor; there are no rails under the car, or, indeed, in the station
  3329.      at all. You look around, and notice about three meters up the east wall
  3330.      is a round tunnel. A passage leads south. "
  3331.     south = cave
  3332.     destination = railway2
  3333.     tunneltime = 3
  3334.     east =
  3335.     {
  3336.         "The tunnel is too high up the wall. You won't be able to enter
  3337.     it without benefit of the railcar. ";
  3338.         return( nil );
  3339.     }
  3340. ;
  3341.  
  3342. class rtunnel: fixeditem
  3343.     sdesc = "tunnel"
  3344.     noun = 'tunnel'
  3345.     verDoEnter( actor ) = {}
  3346.     doEnter( actor ) =
  3347.     {
  3348.         railway1.east;
  3349.     }
  3350. ;
  3351.  
  3352. rtunnel1: rtunnel
  3353.     location = railway1
  3354. ;
  3355.  
  3356. rtunnel2: rtunnel
  3357.     location = railway2
  3358. ;
  3359.  
  3360. railway2: room
  3361.     sdesc = "Subway Station"
  3362.     ldesc = "You're in a subway station. About three meters up the west
  3363.      wall is a tunnel; a passage (at ground level) leads south. A railcar
  3364.      is sitting on the floor in the center of the room. "
  3365.     south = computercenter
  3366.     destination = railway1
  3367.     tunneltime = 3
  3368.     west =
  3369.     {
  3370.         "The tunnel is too high up the wall. You won't be able to enter
  3371.     it without benefit of the railcar. ";
  3372.         return( nil );
  3373.     }
  3374. ;
  3375.  
  3376. computercenter: room
  3377.     sdesc = "Computer Center"
  3378.     ldesc = "You're in a computer room. Unfortunately, all the equipment
  3379.      here is hopelessly out of date and doesn't interest you in the least.
  3380.      The exit is north. "
  3381.     north = railway2
  3382. ;
  3383.  
  3384. compequip: decoration
  3385.     sdesc = "computer equipment"
  3386.     noun = 'equipment'
  3387.     adjective = 'computer'
  3388.     location = computercenter
  3389.     ldesc = "The equipment is all very outdated. It's not the least bit
  3390.      interesting. "
  3391. ;
  3392.  
  3393. randombook: treasure, readable
  3394.     sdesc = "book"
  3395.     ldesc = "The book is entitled \"A Million Random Digits.\" In flipping
  3396.      through the book, you find that it is, in fact, a million random digits,
  3397.      nicely tabulated and individually numbered from 0 to 999,999 (computer
  3398.      people always start numbering at 0). "
  3399.     noun = 'book' 'digits'
  3400.     adjective = 'million' 'random' 'digits' 'numbers'
  3401.     location = computercenter
  3402. ;
  3403.  
  3404. railtunnel: room
  3405.     sdesc = "Tunnel"
  3406.     ldesc = "The tunnel is rather non-descript. "
  3407. ;
  3408.  
  3409. railcar: vehicle, fixeditem, container
  3410.     location = railway1
  3411.     isdroploc = true        // stuff dropped while on board ends up in railcar
  3412.     sdesc = "rail car"
  3413.     noun = 'car' 'railcar'
  3414.     adjective = 'rail'
  3415.     ldesc =
  3416.     {
  3417.         "This is a small rail car, big enough for a couple of people.
  3418.          It has a small control panel, which consists of a green button,
  3419.      a gauge, and a small hole labelled \"Coolant.\" ";
  3420.      if ( funnel.location = railhole )
  3421.         "The hole seems to contain a funnel. ";
  3422.      railmeter.ldesc;
  3423.     }
  3424.     travel =
  3425.     {
  3426.         if ( self.location <> railtunnel )
  3427.     {
  3428.         "\bThe car rises to about three meters off the floor. It then
  3429.         starts to accelerate toward the tunnel, and plunges into the
  3430.         tunnel with a rush of air. ";
  3431.         self.destination := self.location.destination;
  3432.         self.tunneltime := self.location.tunneltime;
  3433.         self.moveInto( railtunnel );
  3434.     }
  3435.     else if ( self.tunneltime > 0 )
  3436.     {
  3437.         "\bThe car races down the tunnel at terrifying speed. ";
  3438.         self.tunneltime := self.tunneltime - 1;
  3439.     }
  3440.     else
  3441.     {
  3442.         "\bThe car starts to decelerate sharply. After a few more seconds,
  3443.         it emerges into a station and glides to a halt. It slowly
  3444.         descends to the ground; once settled, the hum of its engine
  3445.         gradually disappears. ";
  3446.         self.isActive := nil;
  3447.         self.moveInto( self.destination );
  3448.         unnotify( self, #travel );
  3449.     }
  3450.     }
  3451.     checkunboard =
  3452.     {
  3453.         if ( self.isActive )
  3454.     {
  3455.         "Please wait until the railcar has come to a complete and
  3456.         final stop, and the captain has turned off the \"Fasten Seat
  3457.         Belt\" sign. (Actually, I made up the part about the \"Fasten
  3458.         Seat Belt\" sign, but you'll have to wait until the car
  3459.         has stopped nonetheless.) ";
  3460.         return( nil );
  3461.     }
  3462.     else return( true );
  3463.     }
  3464.     out =
  3465.     {
  3466.         if ( self.checkunboard ) pass out;
  3467.     else return( nil );
  3468.     }
  3469.     doUnboard( actor ) =
  3470.     {
  3471.         if ( self.checkunboard ) pass doUnboard;
  3472.     }
  3473. ;
  3474.  
  3475. railmeter: fixeditem
  3476.     location = railcar
  3477.     sdesc = "gauge"
  3478.     noun = 'gauge' 'meter'
  3479.     ldesc =
  3480.     {
  3481.         "The gauge is not labelled with any units you recognize, but
  3482.      the arc is divided into regions colored green, yellow, and red. The
  3483.      needle is currently in the ";
  3484.         if ( railcar.iscooled ) "green"; else "red";
  3485.     " section of the scale. ";
  3486.     }
  3487. ;
  3488.  
  3489. railhole: fixeditem, container
  3490.     location = railcar
  3491.     sdesc = "hole"
  3492.     noun = 'hole'
  3493.     adjective = 'coolant'
  3494.     ldesc =
  3495.     {
  3496.         if ( funnel.location = self )
  3497.         "A funnel is in the hole. ";
  3498.         else if ( railcar.iscooled )
  3499.         "Wisps of water vapor rise from the hole. ";
  3500.     else
  3501.         "The hole is labelled \"Coolant.\" It's about an inch
  3502.         or so in diameter. ";
  3503.     }
  3504.     verIoPourIn( actor ) = {}
  3505.     ioPourIn( actor, dobj ) = { self.ioPutIn( actor, dobj ); }
  3506.     ioPutIn( actor, dobj ) =
  3507.     {
  3508.         if ( dobj = funnel )
  3509.     {
  3510.         "A perfect fit! ";
  3511.         funnel.moveInto( self );
  3512.     }
  3513.     else if ( dobj = ln2 )
  3514.     {
  3515.         if ( funnel.location = self )
  3516.         {
  3517.             if ( railcar.iscooled )
  3518.             "It's already full of liquid nitrogen! ";
  3519.         else
  3520.         {
  3521.             "You carefully pour the liquid nitrogen into the
  3522.             funnel.  It doesn't take very much before the tank
  3523.             is full. ";
  3524.             railcar.iscooled := true;
  3525.         }
  3526.         }
  3527.         else
  3528.         {
  3529.             "The hole is too small; most if not all of the liquid
  3530.         nitrogen you pour spills all around, rather than into
  3531.         the hole. ";
  3532.         }
  3533.     }
  3534.     else
  3535.     {
  3536.         "It won't fit in the hole. ";
  3537.     }
  3538.     }
  3539. ;
  3540.  
  3541. railbutton: buttonitem
  3542.     location = railcar
  3543.     sdesc = "green button"
  3544.     adjective = 'green'
  3545.     doPush( actor ) =
  3546.     {
  3547.         if ( Me.location <> railcar )
  3548.     {
  3549.         "Get in the railcar first. ";
  3550.     }
  3551.     else if ( railcar.isbroken )
  3552.     {
  3553.         "Nothing happens. ";
  3554.     }
  3555.     else if ( railcar.isActive )
  3556.     {
  3557.         "Nothing happens. Perhaps this is because you have
  3558.         already pushed the button quite recently. ";
  3559.     }
  3560.         else if ( railcar.iscooled )
  3561.     {
  3562.         "A low-frequency hum sounds from within the railcar. After
  3563.         a few moments, it starts to levitate off the track. ";
  3564.         notify( railcar, #travel, 0 );
  3565.         railcar.isActive := true;
  3566.     }
  3567.     else
  3568.     {
  3569.         "A low-frequency hum sounds from within the railcar. It grows
  3570.         in strength, and soon starts to vibrate the whole car. You smell
  3571.         the familiar odor of burning electronic components. Suddenly,
  3572.         a bright light flashes underneath the railcar, a cloud of thick
  3573.         black smoke rises, and the humming stops. It appears you have
  3574.         toasted the railcar. ";
  3575.         railcar.isbroken := true;
  3576.     }
  3577.     }
  3578. ;
  3579.  
  3580. biohall1: room
  3581.     sdesc = "Hall"
  3582.     ldesc = "You are in an east-west hallway. A passage labelled \"Bio Lab\"
  3583.      leads south. "
  3584.     west = pitBottom
  3585.     east = biohall2
  3586.     south = biolab
  3587. ;
  3588.  
  3589. biolab: room
  3590.     sdesc = "Bio Lab"
  3591.     ldesc =
  3592.     {
  3593.         "You are in the Biology Lab. All sorts of strange equipment is
  3594.     scattered around the room. A lab bench is in the center of the room,
  3595.     and on one wall is a cabinet (which is ";
  3596.     if ( biocabinet.isopen ) "open"; else "closed";
  3597.     "). A passage leads north. ";
  3598.     }
  3599.     north = biohall1
  3600. ;
  3601.  
  3602. bioEquipment: decoration
  3603.     sdesc = "strange equipment"
  3604.     noun = 'equipment'
  3605.     adjective = 'strange'
  3606.     location = biolab
  3607.     ldesc = "The equipment is entirely unfamiliar to you. "
  3608. ;
  3609.  
  3610. biobench: fixeditem, surface
  3611.     noun = 'bench'
  3612.     adjective = 'lab'
  3613.     sdesc = "lab bench"
  3614.     location = biolab
  3615.     ldesc =
  3616.     {
  3617.         "The bench is topped with one of those strange black rubber surfaces
  3618.     that seemingly all scientific lab benches have. ";
  3619.     pass ldesc;
  3620.     }
  3621. ;
  3622.  
  3623. funnel: container
  3624.     sdesc = "funnel"
  3625.     noun = 'funnel'
  3626.     location = biobench
  3627.     ioPutIn( actor, dobj ) =
  3628.     {
  3629.         if ( dobj = ln2 )
  3630.     {
  3631.         if ( self.location = railhole or self.location = bottle )
  3632.             self.location.ioPutIn( actor, dobj );
  3633.         else
  3634.             "The liquid nitrogen pours through the funnel, lands
  3635.         nowhere in particular, and evaporates. ";
  3636.     }
  3637.     else
  3638.     {
  3639.         "It wouldn't accomplish anything to put ";
  3640.         dobj.thedesc; " into the funnel. ";
  3641.     }
  3642.     }
  3643.     ldesc =
  3644.     {
  3645.         if ( self.location = bottle or self.location = railhole )
  3646.     {
  3647.         "The funnel is stuck into "; self.location.adesc; ". ";
  3648.     }
  3649.     else
  3650.         "It's a normal white plastic funnel, about six inches
  3651.         across at its wide end and about half an inch at its
  3652.         narrow end. ";
  3653.     }
  3654.     verIoPourIn( actor ) = {}
  3655.     ioPourIn( actor, dobj ) = { self.ioPutIn( actor, dobj ); }
  3656. ;
  3657.  
  3658. biohall2: room
  3659.     sdesc = "Hall"
  3660.     ldesc =
  3661.     {
  3662.         "You are at the east end of an east-west hallway. A doorway
  3663.      leads east. ";
  3664.     if ( not self.isseen )
  3665.     {
  3666.         notify( biocreature, #menace, 0 );
  3667.     }
  3668.     }
  3669.     west = biohall1
  3670.     east =
  3671.     {
  3672.         if ( biocreature.location = self )
  3673.     {
  3674.         if ( slime.location = nil )
  3675.         {
  3676.             "The creature grabs you and pushes you back, depositing
  3677.         a huge glob of slime on you in the process. ";
  3678.         slime.moveInto( Me );
  3679.         slime.isworn := true;
  3680.         }
  3681.             else "The creature won't let you pass. ";
  3682.         return( nil );
  3683.     }
  3684.     else return( biooffice );
  3685.     }
  3686. ;
  3687.  
  3688. slime: clothingItem
  3689.     noun = 'glob' 'slime'
  3690.     sdesc = "glob of slime"
  3691.     doWear( actor ) =
  3692.     {
  3693.         "No, thank you. ";
  3694.     }
  3695. ;
  3696.  
  3697. biocreature: Actor
  3698.     location = biohall2
  3699.     sdesc = "creature"
  3700.     noun = 'creature'
  3701.     ldesc = "It looks like the result of a biological experiment that
  3702.       failed (or succeeded, depending on who performed the experiment). "
  3703.     actorDesc = "An enormous creature is blocking the hallway to the east.
  3704.       He (please don't press for details as to how you know, but \"he\"
  3705.       is the appropriate pronoun here) appears to be part human, but
  3706.       exactly what part is not clear. The creature's leathery skin is
  3707.       a bright green, and is largely covered with a thick transluscent
  3708.       slime. "
  3709.     menaceMessage =
  3710.     [
  3711.         'The creature roars a huge roar in your general direction.'
  3712.     'The creature menaces you.'
  3713.     'In a tender moment, the creature produces a magazine and opens up
  3714.      the centerfold. He looks longingly at the picture. After a few
  3715.      moments, he notices you again, and puts away the magazine; as he\'s
  3716.      putting it away, you see that it\'s a copy of "Playmutant."'
  3717.     'The creature looks at you warily.'
  3718.     'The creature growls at you, showing his enormous pointy fangs.'
  3719.     ]
  3720.     menace =
  3721.     {
  3722.         if ( self.location = Me.location )
  3723.     {
  3724.             "\b";
  3725.             say( self.menaceMessage[rand( 5 )]);
  3726.     }
  3727.     }
  3728. ;
  3729.  
  3730. biooffice: room
  3731.     sdesc = "Bio Office"
  3732.     ldesc = "You are in the Biology Office. A large desk dominates the
  3733.      room. The exit is west. "
  3734.     west = biohall2
  3735. ;
  3736.  
  3737. biodesk: fixeditem, surface
  3738.     noun = 'desk'
  3739.     adjective = 'large'
  3740.     location = biooffice
  3741.     sdesc = "desk"
  3742. ;
  3743.  
  3744. biocabinet: openable, fixeditem
  3745.     noun = 'cabinet'
  3746.     location = biolab
  3747.     sdesc = "cabinet"
  3748.     isopen = nil
  3749. ;
  3750.  
  3751. class chemitem: item
  3752.     location = biocabinet
  3753.     noun = 'chemical'
  3754.     plural = 'chemicals'
  3755.     adesc = { "some "; self.sdesc; }
  3756.     ldesc =
  3757.     {
  3758.         "It's a small lump of goo. The only identification is
  3759.          a label reading \""; self.sdesc; ".\" ";
  3760.     }
  3761. ;
  3762.     
  3763. gfxq3: chemitem
  3764.     noun = 'GF-XQ3'
  3765.     sdesc = "GF-XQ3"
  3766. ;
  3767.  
  3768. gfxq9: chemitem
  3769.     noun = 'GF-XQ9'
  3770.     sdesc = "GF-XQ9"
  3771. ;
  3772.  
  3773. polyred: chemitem
  3774.     noun = 'red'
  3775.     adjective = 'poly'
  3776.     sdesc = "Poly Red"
  3777. ;
  3778.  
  3779. polyblue: chemitem
  3780.     noun = 'blue'
  3781.     adjective = 'poly'
  3782.     sdesc = "Poly Blue"
  3783. ;
  3784.  
  3785. compoundT99: chemitem
  3786.     noun = 't99'
  3787.     adjective = 'compound'
  3788.     sdesc = "Compound T99"
  3789. ;
  3790.  
  3791. compoundT30: chemitem
  3792.     noun = 't30'
  3793.     adjective = 'compound'
  3794.     sdesc = "Compound T30"
  3795. ;
  3796.  
  3797. clonemaster: container
  3798.     noun = 'master' 'clonemaster'
  3799.     adjective = 'clone'
  3800.     location = biobench
  3801.     sdesc = "CloneMaster"
  3802.     ldesc =
  3803.     {
  3804.         "The CloneMaster is a simple machine. It consists of a button
  3805.     marked \"Clone,\" and a small receptacle. ";
  3806.      clonerecept.ldesc;
  3807.     }
  3808.     ioPutIn( actor, dobj ) = { clonerecept.ioPutIn( actor, dobj ); }
  3809.     verDoTakeOut( actor, io ) = { clonerecept.verIoTakeOut( actor, io ); }
  3810. ;
  3811.  
  3812. clonerecept: fixeditem, container
  3813.     sdesc = "receptacle"
  3814.     noun = 'receptacle'
  3815.     location = clonemaster
  3816.     ldesc =
  3817.     {
  3818.         "The receptacle is somewhat like that of a kitchen blender. ";
  3819.         pass ldesc;
  3820.     }
  3821. ;
  3822.  
  3823. clonebutton: buttonitem
  3824.     sdesc = "clone button"
  3825.     adjective = 'clone'
  3826.     doPush( actor ) =
  3827.     {
  3828.         if ( slime.location = clonerecept )
  3829.     {
  3830.         "The CloneMaster clicks and whirs for several seconds. ";
  3831.         if ( gfxq3.location = clonerecept and
  3832.          polyblue.location = clonerecept and
  3833.          compoundT99.location = clonerecept
  3834.          and length( clonerecept.contents ) = 4 )
  3835.         {
  3836.             "A monstrous female version (again, don't ask how you know
  3837.          it's female) leaps from the tiny machine";
  3838.             if ( Me.location = biocreature.location )
  3839.         {
  3840.             ". The two monsters look at each other with passion in
  3841.             their mutant eyes. They run to each other with open arms,
  3842.             seemingly in slow motion. They embrace, engage in some
  3843.             mushy behavior, and then run away together to elope. ";
  3844.             biocreature.moveInto( nil );
  3845.             unnotify( biocreature, #menace );
  3846.         }
  3847.         else
  3848.             ", looks around, and, seeing nothing of
  3849.             interest, runs off. ";
  3850.         }
  3851.         else
  3852.             "An exact duplicate of the monstrous creature whose slime
  3853.         you placed in the CloneMaster leaps forth from the tiny
  3854.         machine. He looks at you menacingly for a moment, then
  3855.         runs off into the distance, never to be seen again. ";
  3856.         
  3857.         slime.moveInto( nil );
  3858.     }
  3859.     else "Nothing happens. ";
  3860.     }
  3861.     location = clonemaster
  3862. ;
  3863.  
  3864. omega: treasure
  3865.     sdesc = "Great Seal of the Omega"
  3866.     noun = 'seal' 'omega' 'stamp'
  3867.     adjective = 'great' 'rubber'
  3868.     location = biodesk
  3869.     ldesc = "The Great Seal is a large rubber stamp, about an inch and
  3870.      a half square. The stamp consists of a large circle that is filled by a
  3871.      giant capital omega, under which is the word \"Approved.\" Around the
  3872.      outside of the circle, the words \"The Great Seal of the Omega\" are
  3873.      inscribed. "
  3874. ;
  3875.  
  3876. rope2: fixeditem
  3877.     sdesc = "rope"
  3878.     noun = 'rope'
  3879.     location = pitBottom
  3880.     ldesc = "The rope extends from the opening in the ceiling high above. "
  3881.     verDoTake( actor ) =
  3882.     {
  3883.         "The rope seems to be tied to something from above (which would
  3884.     probably explain why it's extending up to the ceiling in the
  3885.     first place, you deduce in a rare moment of lucid thinking). ";
  3886.     }
  3887.     verDoClimbup( actor ) = {}
  3888.     doClimbup( actor ) = { self.doClimb( actor ); }
  3889.     verDoClimb( actor ) = {}
  3890.     doClimb( actor ) =
  3891.     {
  3892.         "It's a long climb, but you somehow manage it.\b";
  3893.     Me.travelTo( pitTop );
  3894.     }
  3895. ;
  3896.